1 /* 2 * Copyright (C) 2006 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.phone; 18 19 import android.app.ActivityManager; 20 import android.app.AppOpsManager; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.SharedPreferences; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 27 import android.net.Uri; 28 import android.os.AsyncResult; 29 import android.os.Binder; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.os.Looper; 33 import android.os.Message; 34 import android.os.Process; 35 import android.os.ResultReceiver; 36 import android.os.ServiceManager; 37 import android.os.UserHandle; 38 import android.os.UserManager; 39 import android.preference.PreferenceManager; 40 import android.provider.Settings; 41 import android.telecom.PhoneAccount; 42 import android.telecom.PhoneAccountHandle; 43 import android.telecom.TelecomManager; 44 import android.telephony.CarrierConfigManager; 45 import android.telephony.CellInfo; 46 import android.telephony.IccOpenLogicalChannelResponse; 47 import android.telephony.NeighboringCellInfo; 48 import android.telephony.RadioAccessFamily; 49 import android.telephony.ServiceState; 50 import android.telephony.SubscriptionInfo; 51 import android.telephony.SubscriptionManager; 52 import android.telephony.TelephonyManager; 53 import android.telephony.ModemActivityInfo; 54 import android.text.TextUtils; 55 import android.util.ArraySet; 56 import android.util.Log; 57 import android.util.Pair; 58 import android.util.Slog; 59 60 import com.android.ims.ImsManager; 61 import com.android.internal.telephony.CallManager; 62 import com.android.internal.telephony.CellNetworkScanResult; 63 import com.android.internal.telephony.CommandException; 64 import com.android.internal.telephony.DefaultPhoneNotifier; 65 import com.android.internal.telephony.ITelephony; 66 import com.android.internal.telephony.IccCard; 67 import com.android.internal.telephony.MccTable; 68 import com.android.internal.telephony.OperatorInfo; 69 import com.android.internal.telephony.Phone; 70 import com.android.internal.telephony.PhoneFactory; 71 import com.android.internal.telephony.ProxyController; 72 import com.android.internal.telephony.PhoneConstants; 73 import com.android.internal.telephony.RILConstants; 74 import com.android.internal.telephony.SubscriptionController; 75 import com.android.internal.telephony.uicc.IccIoResult; 76 import com.android.internal.telephony.uicc.IccUtils; 77 import com.android.internal.telephony.uicc.UiccCard; 78 import com.android.internal.telephony.uicc.UiccController; 79 import com.android.internal.util.HexDump; 80 import com.android.phone.settings.VoicemailNotificationSettingsUtil; 81 82 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY; 83 84 import java.util.ArrayList; 85 import java.util.Arrays; 86 import java.util.List; 87 import java.util.Locale; 88 import java.util.Map; 89 90 /** 91 * Implementation of the ITelephony interface. 92 */ 93 public class PhoneInterfaceManager extends ITelephony.Stub { 94 private static final String LOG_TAG = "PhoneInterfaceManager"; 95 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2); 96 private static final boolean DBG_LOC = false; 97 private static final boolean DBG_MERGE = false; 98 99 // Message codes used with mMainThreadHandler 100 private static final int CMD_HANDLE_PIN_MMI = 1; 101 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2; 102 private static final int EVENT_NEIGHBORING_CELL_DONE = 3; 103 private static final int CMD_ANSWER_RINGING_CALL = 4; 104 private static final int CMD_END_CALL = 5; // not used yet 105 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7; 106 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8; 107 private static final int CMD_OPEN_CHANNEL = 9; 108 private static final int EVENT_OPEN_CHANNEL_DONE = 10; 109 private static final int CMD_CLOSE_CHANNEL = 11; 110 private static final int EVENT_CLOSE_CHANNEL_DONE = 12; 111 private static final int CMD_NV_READ_ITEM = 13; 112 private static final int EVENT_NV_READ_ITEM_DONE = 14; 113 private static final int CMD_NV_WRITE_ITEM = 15; 114 private static final int EVENT_NV_WRITE_ITEM_DONE = 16; 115 private static final int CMD_NV_WRITE_CDMA_PRL = 17; 116 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18; 117 private static final int CMD_NV_RESET_CONFIG = 19; 118 private static final int EVENT_NV_RESET_CONFIG_DONE = 20; 119 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21; 120 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22; 121 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23; 122 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24; 123 private static final int CMD_SEND_ENVELOPE = 25; 124 private static final int EVENT_SEND_ENVELOPE_DONE = 26; 125 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27; 126 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28; 127 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29; 128 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30; 129 private static final int CMD_EXCHANGE_SIM_IO = 31; 130 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32; 131 private static final int CMD_SET_VOICEMAIL_NUMBER = 33; 132 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34; 133 private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35; 134 private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36; 135 private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37; 136 private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38; 137 private static final int CMD_PERFORM_NETWORK_SCAN = 39; 138 private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40; 139 private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41; 140 private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42; 141 142 /** The singleton instance. */ 143 private static PhoneInterfaceManager sInstance; 144 145 private PhoneGlobals mApp; 146 private Phone mPhone; 147 private CallManager mCM; 148 private UserManager mUserManager; 149 private AppOpsManager mAppOps; 150 private MainThreadHandler mMainThreadHandler; 151 private SubscriptionController mSubscriptionController; 152 private SharedPreferences mTelephonySharedPreferences; 153 154 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_"; 155 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_"; 156 private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_"; 157 158 /** 159 * A request object to use for transmitting data to an ICC. 160 */ 161 private static final class IccAPDUArgument { 162 public int channel, cla, command, p1, p2, p3; 163 public String data; 164 IccAPDUArgument(int channel, int cla, int command, int p1, int p2, int p3, String data)165 public IccAPDUArgument(int channel, int cla, int command, 166 int p1, int p2, int p3, String data) { 167 this.channel = channel; 168 this.cla = cla; 169 this.command = command; 170 this.p1 = p1; 171 this.p2 = p2; 172 this.p3 = p3; 173 this.data = data; 174 } 175 } 176 177 /** 178 * A request object to use for transmitting data to an ICC. 179 */ 180 private static final class ManualNetworkSelectionArgument { 181 public OperatorInfo operatorInfo; 182 public boolean persistSelection; 183 ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection)184 public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) { 185 this.operatorInfo = operatorInfo; 186 this.persistSelection = persistSelection; 187 } 188 } 189 190 /** 191 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the 192 * request after sending. The main thread will notify the request when it is complete. 193 */ 194 private static final class MainThreadRequest { 195 /** The argument to use for the request */ 196 public Object argument; 197 /** The result of the request that is run on the main thread */ 198 public Object result; 199 // The subscriber id that this request applies to. Defaults to 200 // SubscriptionManager.INVALID_SUBSCRIPTION_ID 201 public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 202 MainThreadRequest(Object argument)203 public MainThreadRequest(Object argument) { 204 this.argument = argument; 205 } 206 MainThreadRequest(Object argument, Integer subId)207 public MainThreadRequest(Object argument, Integer subId) { 208 this.argument = argument; 209 if (subId != null) { 210 this.subId = subId; 211 } 212 } 213 } 214 215 private static final class IncomingThirdPartyCallArgs { 216 public final ComponentName component; 217 public final String callId; 218 public final String callerDisplayName; 219 IncomingThirdPartyCallArgs(ComponentName component, String callId, String callerDisplayName)220 public IncomingThirdPartyCallArgs(ComponentName component, String callId, 221 String callerDisplayName) { 222 this.component = component; 223 this.callId = callId; 224 this.callerDisplayName = callerDisplayName; 225 } 226 } 227 228 /** 229 * A handler that processes messages on the main thread in the phone process. Since many 230 * of the Phone calls are not thread safe this is needed to shuttle the requests from the 231 * inbound binder threads to the main thread in the phone process. The Binder thread 232 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting 233 * on, which will be notified when the operation completes and will contain the result of the 234 * request. 235 * 236 * <p>If a MainThreadRequest object is provided in the msg.obj field, 237 * note that request.result must be set to something non-null for the calling thread to 238 * unblock. 239 */ 240 private final class MainThreadHandler extends Handler { 241 @Override handleMessage(Message msg)242 public void handleMessage(Message msg) { 243 MainThreadRequest request; 244 Message onCompleted; 245 AsyncResult ar; 246 UiccCard uiccCard; 247 IccAPDUArgument iccArgument; 248 249 switch (msg.what) { 250 case CMD_HANDLE_PIN_MMI: { 251 request = (MainThreadRequest) msg.obj; 252 final Phone phone = getPhoneFromRequest(request); 253 request.result = phone != null ? 254 getPhoneFromRequest(request).handlePinMmi((String) request.argument) 255 : false; 256 // Wake up the requesting thread 257 synchronized (request) { 258 request.notifyAll(); 259 } 260 break; 261 } 262 263 case CMD_HANDLE_NEIGHBORING_CELL: 264 request = (MainThreadRequest) msg.obj; 265 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE, 266 request); 267 mPhone.getNeighboringCids(onCompleted); 268 break; 269 270 case EVENT_NEIGHBORING_CELL_DONE: 271 ar = (AsyncResult) msg.obj; 272 request = (MainThreadRequest) ar.userObj; 273 if (ar.exception == null && ar.result != null) { 274 request.result = ar.result; 275 } else { 276 // create an empty list to notify the waiting thread 277 request.result = new ArrayList<NeighboringCellInfo>(0); 278 } 279 // Wake up the requesting thread 280 synchronized (request) { 281 request.notifyAll(); 282 } 283 break; 284 285 case CMD_ANSWER_RINGING_CALL: 286 request = (MainThreadRequest) msg.obj; 287 int answer_subId = request.subId; 288 answerRingingCallInternal(answer_subId); 289 break; 290 291 case CMD_END_CALL: 292 request = (MainThreadRequest) msg.obj; 293 int end_subId = request.subId; 294 final boolean hungUp; 295 Phone phone = getPhone(end_subId); 296 if (phone == null) { 297 if (DBG) log("CMD_END_CALL: no phone for id: " + end_subId); 298 break; 299 } 300 int phoneType = phone.getPhoneType(); 301 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { 302 // CDMA: If the user presses the Power button we treat it as 303 // ending the complete call session 304 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId)); 305 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { 306 // GSM: End the call as per the Phone state 307 hungUp = PhoneUtils.hangup(mCM); 308 } else { 309 throw new IllegalStateException("Unexpected phone type: " + phoneType); 310 } 311 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up")); 312 request.result = hungUp; 313 // Wake up the requesting thread 314 synchronized (request) { 315 request.notifyAll(); 316 } 317 break; 318 319 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL: 320 request = (MainThreadRequest) msg.obj; 321 iccArgument = (IccAPDUArgument) request.argument; 322 uiccCard = getUiccCardFromRequest(request); 323 if (uiccCard == null) { 324 loge("iccTransmitApduLogicalChannel: No UICC"); 325 request.result = new IccIoResult(0x6F, 0, (byte[])null); 326 synchronized (request) { 327 request.notifyAll(); 328 } 329 } else { 330 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, 331 request); 332 uiccCard.iccTransmitApduLogicalChannel( 333 iccArgument.channel, iccArgument.cla, iccArgument.command, 334 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data, 335 onCompleted); 336 } 337 break; 338 339 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE: 340 ar = (AsyncResult) msg.obj; 341 request = (MainThreadRequest) ar.userObj; 342 if (ar.exception == null && ar.result != null) { 343 request.result = ar.result; 344 } else { 345 request.result = new IccIoResult(0x6F, 0, (byte[])null); 346 if (ar.result == null) { 347 loge("iccTransmitApduLogicalChannel: Empty response"); 348 } else if (ar.exception instanceof CommandException) { 349 loge("iccTransmitApduLogicalChannel: CommandException: " + 350 ar.exception); 351 } else { 352 loge("iccTransmitApduLogicalChannel: Unknown exception"); 353 } 354 } 355 synchronized (request) { 356 request.notifyAll(); 357 } 358 break; 359 360 case CMD_TRANSMIT_APDU_BASIC_CHANNEL: 361 request = (MainThreadRequest) msg.obj; 362 iccArgument = (IccAPDUArgument) request.argument; 363 uiccCard = getUiccCardFromRequest(request); 364 if (uiccCard == null) { 365 loge("iccTransmitApduBasicChannel: No UICC"); 366 request.result = new IccIoResult(0x6F, 0, (byte[])null); 367 synchronized (request) { 368 request.notifyAll(); 369 } 370 } else { 371 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, 372 request); 373 uiccCard.iccTransmitApduBasicChannel( 374 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2, 375 iccArgument.p3, iccArgument.data, onCompleted); 376 } 377 break; 378 379 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE: 380 ar = (AsyncResult) msg.obj; 381 request = (MainThreadRequest) ar.userObj; 382 if (ar.exception == null && ar.result != null) { 383 request.result = ar.result; 384 } else { 385 request.result = new IccIoResult(0x6F, 0, (byte[])null); 386 if (ar.result == null) { 387 loge("iccTransmitApduBasicChannel: Empty response"); 388 } else if (ar.exception instanceof CommandException) { 389 loge("iccTransmitApduBasicChannel: CommandException: " + 390 ar.exception); 391 } else { 392 loge("iccTransmitApduBasicChannel: Unknown exception"); 393 } 394 } 395 synchronized (request) { 396 request.notifyAll(); 397 } 398 break; 399 400 case CMD_EXCHANGE_SIM_IO: 401 request = (MainThreadRequest) msg.obj; 402 iccArgument = (IccAPDUArgument) request.argument; 403 uiccCard = getUiccCardFromRequest(request); 404 if (uiccCard == null) { 405 loge("iccExchangeSimIO: No UICC"); 406 request.result = new IccIoResult(0x6F, 0, (byte[])null); 407 synchronized (request) { 408 request.notifyAll(); 409 } 410 } else { 411 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE, 412 request); 413 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */ 414 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3, 415 iccArgument.data, onCompleted); 416 } 417 break; 418 419 case EVENT_EXCHANGE_SIM_IO_DONE: 420 ar = (AsyncResult) msg.obj; 421 request = (MainThreadRequest) ar.userObj; 422 if (ar.exception == null && ar.result != null) { 423 request.result = ar.result; 424 } else { 425 request.result = new IccIoResult(0x6f, 0, (byte[])null); 426 } 427 synchronized (request) { 428 request.notifyAll(); 429 } 430 break; 431 432 case CMD_SEND_ENVELOPE: 433 request = (MainThreadRequest) msg.obj; 434 uiccCard = getUiccCardFromRequest(request); 435 if (uiccCard == null) { 436 loge("sendEnvelopeWithStatus: No UICC"); 437 request.result = new IccIoResult(0x6F, 0, (byte[])null); 438 synchronized (request) { 439 request.notifyAll(); 440 } 441 } else { 442 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request); 443 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted); 444 } 445 break; 446 447 case EVENT_SEND_ENVELOPE_DONE: 448 ar = (AsyncResult) msg.obj; 449 request = (MainThreadRequest) ar.userObj; 450 if (ar.exception == null && ar.result != null) { 451 request.result = ar.result; 452 } else { 453 request.result = new IccIoResult(0x6F, 0, (byte[])null); 454 if (ar.result == null) { 455 loge("sendEnvelopeWithStatus: Empty response"); 456 } else if (ar.exception instanceof CommandException) { 457 loge("sendEnvelopeWithStatus: CommandException: " + 458 ar.exception); 459 } else { 460 loge("sendEnvelopeWithStatus: exception:" + ar.exception); 461 } 462 } 463 synchronized (request) { 464 request.notifyAll(); 465 } 466 break; 467 468 case CMD_OPEN_CHANNEL: 469 request = (MainThreadRequest) msg.obj; 470 uiccCard = getUiccCardFromRequest(request); 471 if (uiccCard == null) { 472 loge("iccOpenLogicalChannel: No UICC"); 473 request.result = new IccOpenLogicalChannelResponse(-1, 474 IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null); 475 synchronized (request) { 476 request.notifyAll(); 477 } 478 } else { 479 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request); 480 uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted); 481 } 482 break; 483 484 case EVENT_OPEN_CHANNEL_DONE: 485 ar = (AsyncResult) msg.obj; 486 request = (MainThreadRequest) ar.userObj; 487 IccOpenLogicalChannelResponse openChannelResp; 488 if (ar.exception == null && ar.result != null) { 489 int[] result = (int[]) ar.result; 490 int channelId = result[0]; 491 byte[] selectResponse = null; 492 if (result.length > 1) { 493 selectResponse = new byte[result.length - 1]; 494 for (int i = 1; i < result.length; ++i) { 495 selectResponse[i - 1] = (byte) result[i]; 496 } 497 } 498 openChannelResp = new IccOpenLogicalChannelResponse(channelId, 499 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse); 500 } else { 501 if (ar.result == null) { 502 loge("iccOpenLogicalChannel: Empty response"); 503 } 504 if (ar.exception != null) { 505 loge("iccOpenLogicalChannel: Exception: " + ar.exception); 506 } 507 508 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR; 509 if (ar.exception instanceof CommandException) { 510 CommandException.Error error = 511 ((CommandException) (ar.exception)).getCommandError(); 512 if (error == CommandException.Error.MISSING_RESOURCE) { 513 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE; 514 } else if (error == CommandException.Error.NO_SUCH_ELEMENT) { 515 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT; 516 } 517 } 518 openChannelResp = new IccOpenLogicalChannelResponse( 519 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null); 520 } 521 request.result = openChannelResp; 522 synchronized (request) { 523 request.notifyAll(); 524 } 525 break; 526 527 case CMD_CLOSE_CHANNEL: 528 request = (MainThreadRequest) msg.obj; 529 uiccCard = getUiccCardFromRequest(request); 530 if (uiccCard == null) { 531 loge("iccCloseLogicalChannel: No UICC"); 532 request.result = new IccIoResult(0x6F, 0, (byte[])null); 533 synchronized (request) { 534 request.notifyAll(); 535 } 536 } else { 537 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request); 538 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted); 539 } 540 break; 541 542 case EVENT_CLOSE_CHANNEL_DONE: 543 handleNullReturnEvent(msg, "iccCloseLogicalChannel"); 544 break; 545 546 case CMD_NV_READ_ITEM: 547 request = (MainThreadRequest) msg.obj; 548 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request); 549 mPhone.nvReadItem((Integer) request.argument, onCompleted); 550 break; 551 552 case EVENT_NV_READ_ITEM_DONE: 553 ar = (AsyncResult) msg.obj; 554 request = (MainThreadRequest) ar.userObj; 555 if (ar.exception == null && ar.result != null) { 556 request.result = ar.result; // String 557 } else { 558 request.result = ""; 559 if (ar.result == null) { 560 loge("nvReadItem: Empty response"); 561 } else if (ar.exception instanceof CommandException) { 562 loge("nvReadItem: CommandException: " + 563 ar.exception); 564 } else { 565 loge("nvReadItem: Unknown exception"); 566 } 567 } 568 synchronized (request) { 569 request.notifyAll(); 570 } 571 break; 572 573 case CMD_NV_WRITE_ITEM: 574 request = (MainThreadRequest) msg.obj; 575 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request); 576 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument; 577 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted); 578 break; 579 580 case EVENT_NV_WRITE_ITEM_DONE: 581 handleNullReturnEvent(msg, "nvWriteItem"); 582 break; 583 584 case CMD_NV_WRITE_CDMA_PRL: 585 request = (MainThreadRequest) msg.obj; 586 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request); 587 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted); 588 break; 589 590 case EVENT_NV_WRITE_CDMA_PRL_DONE: 591 handleNullReturnEvent(msg, "nvWriteCdmaPrl"); 592 break; 593 594 case CMD_NV_RESET_CONFIG: 595 request = (MainThreadRequest) msg.obj; 596 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request); 597 mPhone.nvResetConfig((Integer) request.argument, onCompleted); 598 break; 599 600 case EVENT_NV_RESET_CONFIG_DONE: 601 handleNullReturnEvent(msg, "nvResetConfig"); 602 break; 603 604 case CMD_GET_PREFERRED_NETWORK_TYPE: 605 request = (MainThreadRequest) msg.obj; 606 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request); 607 getPhoneFromRequest(request).getPreferredNetworkType(onCompleted); 608 break; 609 610 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE: 611 ar = (AsyncResult) msg.obj; 612 request = (MainThreadRequest) ar.userObj; 613 if (ar.exception == null && ar.result != null) { 614 request.result = ar.result; // Integer 615 } else { 616 request.result = null; 617 if (ar.result == null) { 618 loge("getPreferredNetworkType: Empty response"); 619 } else if (ar.exception instanceof CommandException) { 620 loge("getPreferredNetworkType: CommandException: " + 621 ar.exception); 622 } else { 623 loge("getPreferredNetworkType: Unknown exception"); 624 } 625 } 626 synchronized (request) { 627 request.notifyAll(); 628 } 629 break; 630 631 case CMD_SET_PREFERRED_NETWORK_TYPE: 632 request = (MainThreadRequest) msg.obj; 633 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request); 634 int networkType = (Integer) request.argument; 635 getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted); 636 break; 637 638 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE: 639 handleNullReturnEvent(msg, "setPreferredNetworkType"); 640 break; 641 642 case CMD_INVOKE_OEM_RIL_REQUEST_RAW: 643 request = (MainThreadRequest)msg.obj; 644 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request); 645 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted); 646 break; 647 648 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE: 649 ar = (AsyncResult)msg.obj; 650 request = (MainThreadRequest)ar.userObj; 651 request.result = ar; 652 synchronized (request) { 653 request.notifyAll(); 654 } 655 break; 656 657 case CMD_SET_VOICEMAIL_NUMBER: 658 request = (MainThreadRequest) msg.obj; 659 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request); 660 Pair<String, String> tagNum = (Pair<String, String>) request.argument; 661 getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second, 662 onCompleted); 663 break; 664 665 case EVENT_SET_VOICEMAIL_NUMBER_DONE: 666 handleNullReturnEvent(msg, "setVoicemailNumber"); 667 break; 668 669 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC: 670 request = (MainThreadRequest) msg.obj; 671 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE, 672 request); 673 getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted); 674 break; 675 676 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE: 677 handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic"); 678 break; 679 680 case CMD_PERFORM_NETWORK_SCAN: 681 request = (MainThreadRequest) msg.obj; 682 onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request); 683 getPhoneFromRequest(request).getAvailableNetworks(onCompleted); 684 break; 685 686 case EVENT_PERFORM_NETWORK_SCAN_DONE: 687 ar = (AsyncResult) msg.obj; 688 request = (MainThreadRequest) ar.userObj; 689 CellNetworkScanResult cellScanResult; 690 if (ar.exception == null && ar.result != null) { 691 cellScanResult = new CellNetworkScanResult( 692 CellNetworkScanResult.STATUS_SUCCESS, 693 (List<OperatorInfo>) ar.result); 694 } else { 695 if (ar.result == null) { 696 loge("getCellNetworkScanResults: Empty response"); 697 } 698 if (ar.exception != null) { 699 loge("getCellNetworkScanResults: Exception: " + ar.exception); 700 } 701 int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR; 702 if (ar.exception instanceof CommandException) { 703 CommandException.Error error = 704 ((CommandException) (ar.exception)).getCommandError(); 705 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) { 706 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE; 707 } else if (error == CommandException.Error.GENERIC_FAILURE) { 708 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE; 709 } 710 } 711 cellScanResult = new CellNetworkScanResult(errorCode, null); 712 } 713 request.result = cellScanResult; 714 synchronized (request) { 715 request.notifyAll(); 716 } 717 break; 718 719 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL: 720 request = (MainThreadRequest) msg.obj; 721 ManualNetworkSelectionArgument selArg = 722 (ManualNetworkSelectionArgument) request.argument; 723 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE, 724 request); 725 getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo, 726 selArg.persistSelection, onCompleted); 727 break; 728 729 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE: 730 handleNullReturnEvent(msg, "setNetworkSelectionModeManual"); 731 break; 732 733 case CMD_GET_MODEM_ACTIVITY_INFO: 734 request = (MainThreadRequest) msg.obj; 735 onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request); 736 mPhone.getModemActivityInfo(onCompleted); 737 break; 738 739 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE: 740 ar = (AsyncResult) msg.obj; 741 request = (MainThreadRequest) ar.userObj; 742 if (ar.exception == null && ar.result != null) { 743 request.result = ar.result; 744 } else { 745 if (ar.result == null) { 746 loge("queryModemActivityInfo: Empty response"); 747 } else if (ar.exception instanceof CommandException) { 748 loge("queryModemActivityInfo: CommandException: " + 749 ar.exception); 750 } else { 751 loge("queryModemActivityInfo: Unknown exception"); 752 } 753 } 754 // Result cannot be null. Return ModemActivityInfo with all fields set to 0. 755 if (request.result == null) { 756 request.result = new ModemActivityInfo(0, 0, 0, null, 0, 0); 757 } 758 synchronized (request) { 759 request.notifyAll(); 760 } 761 break; 762 763 default: 764 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what); 765 break; 766 } 767 } 768 handleNullReturnEvent(Message msg, String command)769 private void handleNullReturnEvent(Message msg, String command) { 770 AsyncResult ar = (AsyncResult) msg.obj; 771 MainThreadRequest request = (MainThreadRequest) ar.userObj; 772 if (ar.exception == null) { 773 request.result = true; 774 } else { 775 request.result = false; 776 if (ar.exception instanceof CommandException) { 777 loge(command + ": CommandException: " + ar.exception); 778 } else { 779 loge(command + ": Unknown exception"); 780 } 781 } 782 synchronized (request) { 783 request.notifyAll(); 784 } 785 } 786 } 787 788 /** 789 * Posts the specified command to be executed on the main thread, 790 * waits for the request to complete, and returns the result. 791 * @see #sendRequestAsync 792 */ sendRequest(int command, Object argument)793 private Object sendRequest(int command, Object argument) { 794 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID); 795 } 796 797 /** 798 * Posts the specified command to be executed on the main thread, 799 * waits for the request to complete, and returns the result. 800 * @see #sendRequestAsync 801 */ sendRequest(int command, Object argument, Integer subId)802 private Object sendRequest(int command, Object argument, Integer subId) { 803 if (Looper.myLooper() == mMainThreadHandler.getLooper()) { 804 throw new RuntimeException("This method will deadlock if called from the main thread."); 805 } 806 807 MainThreadRequest request = new MainThreadRequest(argument, subId); 808 Message msg = mMainThreadHandler.obtainMessage(command, request); 809 msg.sendToTarget(); 810 811 // Wait for the request to complete 812 synchronized (request) { 813 while (request.result == null) { 814 try { 815 request.wait(); 816 } catch (InterruptedException e) { 817 // Do nothing, go back and wait until the request is complete 818 } 819 } 820 } 821 return request.result; 822 } 823 824 /** 825 * Asynchronous ("fire and forget") version of sendRequest(): 826 * Posts the specified command to be executed on the main thread, and 827 * returns immediately. 828 * @see #sendRequest 829 */ sendRequestAsync(int command)830 private void sendRequestAsync(int command) { 831 mMainThreadHandler.sendEmptyMessage(command); 832 } 833 834 /** 835 * Same as {@link #sendRequestAsync(int)} except it takes an argument. 836 * @see {@link #sendRequest(int,Object)} 837 */ sendRequestAsync(int command, Object argument)838 private void sendRequestAsync(int command, Object argument) { 839 MainThreadRequest request = new MainThreadRequest(argument); 840 Message msg = mMainThreadHandler.obtainMessage(command, request); 841 msg.sendToTarget(); 842 } 843 844 /** 845 * Initialize the singleton PhoneInterfaceManager instance. 846 * This is only done once, at startup, from PhoneApp.onCreate(). 847 */ init(PhoneGlobals app, Phone phone)848 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) { 849 synchronized (PhoneInterfaceManager.class) { 850 if (sInstance == null) { 851 sInstance = new PhoneInterfaceManager(app, phone); 852 } else { 853 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance); 854 } 855 return sInstance; 856 } 857 } 858 859 /** Private constructor; @see init() */ PhoneInterfaceManager(PhoneGlobals app, Phone phone)860 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) { 861 mApp = app; 862 mPhone = phone; 863 mCM = PhoneGlobals.getInstance().mCM; 864 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE); 865 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE); 866 mMainThreadHandler = new MainThreadHandler(); 867 mTelephonySharedPreferences = 868 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()); 869 mSubscriptionController = SubscriptionController.getInstance(); 870 871 publish(); 872 } 873 publish()874 private void publish() { 875 if (DBG) log("publish: " + this); 876 877 ServiceManager.addService("phone", this); 878 } 879 getPhoneFromRequest(MainThreadRequest request)880 private Phone getPhoneFromRequest(MainThreadRequest request) { 881 return (request.subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) 882 ? mPhone : getPhone(request.subId); 883 } 884 getUiccCardFromRequest(MainThreadRequest request)885 private UiccCard getUiccCardFromRequest(MainThreadRequest request) { 886 Phone phone = getPhoneFromRequest(request); 887 return phone == null ? null : 888 UiccController.getInstance().getUiccCard(phone.getPhoneId()); 889 } 890 891 // returns phone associated with the subId. getPhone(int subId)892 private Phone getPhone(int subId) { 893 return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId)); 894 } 895 // 896 // Implementation of the ITelephony interface. 897 // 898 dial(String number)899 public void dial(String number) { 900 dialForSubscriber(getPreferredVoiceSubscription(), number); 901 } 902 dialForSubscriber(int subId, String number)903 public void dialForSubscriber(int subId, String number) { 904 if (DBG) log("dial: " + number); 905 // No permission check needed here: This is just a wrapper around the 906 // ACTION_DIAL intent, which is available to any app since it puts up 907 // the UI before it does anything. 908 909 String url = createTelUrl(number); 910 if (url == null) { 911 return; 912 } 913 914 // PENDING: should we just silently fail if phone is offhook or ringing? 915 PhoneConstants.State state = mCM.getState(subId); 916 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) { 917 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); 918 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 919 mApp.startActivity(intent); 920 } 921 } 922 call(String callingPackage, String number)923 public void call(String callingPackage, String number) { 924 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number); 925 } 926 callForSubscriber(int subId, String callingPackage, String number)927 public void callForSubscriber(int subId, String callingPackage, String number) { 928 if (DBG) log("call: " + number); 929 930 // This is just a wrapper around the ACTION_CALL intent, but we still 931 // need to do a permission check since we're calling startActivity() 932 // from the context of the phone app. 933 enforceCallPermission(); 934 935 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage) 936 != AppOpsManager.MODE_ALLOWED) { 937 return; 938 } 939 940 String url = createTelUrl(number); 941 if (url == null) { 942 return; 943 } 944 945 boolean isValid = false; 946 final List<SubscriptionInfo> slist = getActiveSubscriptionInfoList(); 947 if (slist != null) { 948 for (SubscriptionInfo subInfoRecord : slist) { 949 if (subInfoRecord.getSubscriptionId() == subId) { 950 isValid = true; 951 break; 952 } 953 } 954 } 955 if (isValid == false) { 956 return; 957 } 958 959 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url)); 960 intent.putExtra(SUBSCRIPTION_KEY, subId); 961 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 962 mApp.startActivity(intent); 963 } 964 965 /** 966 * End a call based on call state 967 * @return true is a call was ended 968 */ endCall()969 public boolean endCall() { 970 return endCallForSubscriber(getDefaultSubscription()); 971 } 972 973 /** 974 * End a call based on the call state of the subId 975 * @return true is a call was ended 976 */ endCallForSubscriber(int subId)977 public boolean endCallForSubscriber(int subId) { 978 enforceCallPermission(); 979 return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId)); 980 } 981 answerRingingCall()982 public void answerRingingCall() { 983 answerRingingCallForSubscriber(getDefaultSubscription()); 984 } 985 answerRingingCallForSubscriber(int subId)986 public void answerRingingCallForSubscriber(int subId) { 987 if (DBG) log("answerRingingCall..."); 988 // TODO: there should eventually be a separate "ANSWER_PHONE" permission, 989 // but that can probably wait till the big TelephonyManager API overhaul. 990 // For now, protect this call with the MODIFY_PHONE_STATE permission. 991 enforceModifyPermission(); 992 sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId)); 993 } 994 995 /** 996 * Make the actual telephony calls to implement answerRingingCall(). 997 * This should only be called from the main thread of the Phone app. 998 * @see #answerRingingCall 999 * 1000 * TODO: it would be nice to return true if we answered the call, or 1001 * false if there wasn't actually a ringing incoming call, or some 1002 * other error occurred. (In other words, pass back the return value 1003 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().) 1004 * But that would require calling this method via sendRequest() rather 1005 * than sendRequestAsync(), and right now we don't actually *need* that 1006 * return value, so let's just return void for now. 1007 */ answerRingingCallInternal(int subId)1008 private void answerRingingCallInternal(int subId) { 1009 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle(); 1010 if (hasRingingCall) { 1011 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle(); 1012 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle(); 1013 if (hasActiveCall && hasHoldingCall) { 1014 // Both lines are in use! 1015 // TODO: provide a flag to let the caller specify what 1016 // policy to use if both lines are in use. (The current 1017 // behavior is hardwired to "answer incoming, end ongoing", 1018 // which is how the CALL button is specced to behave.) 1019 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall()); 1020 return; 1021 } else { 1022 // answerCall() will automatically hold the current active 1023 // call, if there is one. 1024 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall()); 1025 return; 1026 } 1027 } else { 1028 // No call was ringing. 1029 return; 1030 } 1031 } 1032 1033 /** 1034 * This method is no longer used and can be removed once TelephonyManager stops referring to it. 1035 */ silenceRinger()1036 public void silenceRinger() { 1037 Log.e(LOG_TAG, "silenseRinger not supported"); 1038 } 1039 1040 @Override isOffhook(String callingPackage)1041 public boolean isOffhook(String callingPackage) { 1042 return isOffhookForSubscriber(getDefaultSubscription(), callingPackage); 1043 } 1044 1045 @Override isOffhookForSubscriber(int subId, String callingPackage)1046 public boolean isOffhookForSubscriber(int subId, String callingPackage) { 1047 if (!canReadPhoneState(callingPackage, "isOffhookForSubscriber")) { 1048 return false; 1049 } 1050 1051 final Phone phone = getPhone(subId); 1052 if (phone != null) { 1053 return (phone.getState() == PhoneConstants.State.OFFHOOK); 1054 } else { 1055 return false; 1056 } 1057 } 1058 1059 @Override isRinging(String callingPackage)1060 public boolean isRinging(String callingPackage) { 1061 return (isRingingForSubscriber(getDefaultSubscription(), callingPackage)); 1062 } 1063 1064 @Override isRingingForSubscriber(int subId, String callingPackage)1065 public boolean isRingingForSubscriber(int subId, String callingPackage) { 1066 if (!canReadPhoneState(callingPackage, "isRingingForSubscriber")) { 1067 return false; 1068 } 1069 1070 final Phone phone = getPhone(subId); 1071 if (phone != null) { 1072 return (phone.getState() == PhoneConstants.State.RINGING); 1073 } else { 1074 return false; 1075 } 1076 } 1077 1078 @Override isIdle(String callingPackage)1079 public boolean isIdle(String callingPackage) { 1080 return isIdleForSubscriber(getDefaultSubscription(), callingPackage); 1081 } 1082 1083 @Override isIdleForSubscriber(int subId, String callingPackage)1084 public boolean isIdleForSubscriber(int subId, String callingPackage) { 1085 if (!canReadPhoneState(callingPackage, "isIdleForSubscriber")) { 1086 return false; 1087 } 1088 1089 final Phone phone = getPhone(subId); 1090 if (phone != null) { 1091 return (phone.getState() == PhoneConstants.State.IDLE); 1092 } else { 1093 return false; 1094 } 1095 } 1096 supplyPin(String pin)1097 public boolean supplyPin(String pin) { 1098 return supplyPinForSubscriber(getDefaultSubscription(), pin); 1099 } 1100 supplyPinForSubscriber(int subId, String pin)1101 public boolean supplyPinForSubscriber(int subId, String pin) { 1102 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin); 1103 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false; 1104 } 1105 supplyPuk(String puk, String pin)1106 public boolean supplyPuk(String puk, String pin) { 1107 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin); 1108 } 1109 supplyPukForSubscriber(int subId, String puk, String pin)1110 public boolean supplyPukForSubscriber(int subId, String puk, String pin) { 1111 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin); 1112 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false; 1113 } 1114 1115 /** {@hide} */ supplyPinReportResult(String pin)1116 public int[] supplyPinReportResult(String pin) { 1117 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin); 1118 } 1119 supplyPinReportResultForSubscriber(int subId, String pin)1120 public int[] supplyPinReportResultForSubscriber(int subId, String pin) { 1121 enforceModifyPermission(); 1122 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard()); 1123 checkSimPin.start(); 1124 return checkSimPin.unlockSim(null, pin); 1125 } 1126 1127 /** {@hide} */ supplyPukReportResult(String puk, String pin)1128 public int[] supplyPukReportResult(String puk, String pin) { 1129 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin); 1130 } 1131 supplyPukReportResultForSubscriber(int subId, String puk, String pin)1132 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) { 1133 enforceModifyPermission(); 1134 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard()); 1135 checkSimPuk.start(); 1136 return checkSimPuk.unlockSim(puk, pin); 1137 } 1138 1139 /** 1140 * Helper thread to turn async call to SimCard#supplyPin into 1141 * a synchronous one. 1142 */ 1143 private static class UnlockSim extends Thread { 1144 1145 private final IccCard mSimCard; 1146 1147 private boolean mDone = false; 1148 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE; 1149 private int mRetryCount = -1; 1150 1151 // For replies from SimCard interface 1152 private Handler mHandler; 1153 1154 // For async handler to identify request type 1155 private static final int SUPPLY_PIN_COMPLETE = 100; 1156 UnlockSim(IccCard simCard)1157 public UnlockSim(IccCard simCard) { 1158 mSimCard = simCard; 1159 } 1160 1161 @Override run()1162 public void run() { 1163 Looper.prepare(); 1164 synchronized (UnlockSim.this) { 1165 mHandler = new Handler() { 1166 @Override 1167 public void handleMessage(Message msg) { 1168 AsyncResult ar = (AsyncResult) msg.obj; 1169 switch (msg.what) { 1170 case SUPPLY_PIN_COMPLETE: 1171 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE"); 1172 synchronized (UnlockSim.this) { 1173 mRetryCount = msg.arg1; 1174 if (ar.exception != null) { 1175 if (ar.exception instanceof CommandException && 1176 ((CommandException)(ar.exception)).getCommandError() 1177 == CommandException.Error.PASSWORD_INCORRECT) { 1178 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT; 1179 } else { 1180 mResult = PhoneConstants.PIN_GENERAL_FAILURE; 1181 } 1182 } else { 1183 mResult = PhoneConstants.PIN_RESULT_SUCCESS; 1184 } 1185 mDone = true; 1186 UnlockSim.this.notifyAll(); 1187 } 1188 break; 1189 } 1190 } 1191 }; 1192 UnlockSim.this.notifyAll(); 1193 } 1194 Looper.loop(); 1195 } 1196 1197 /* 1198 * Use PIN or PUK to unlock SIM card 1199 * 1200 * If PUK is null, unlock SIM card with PIN 1201 * 1202 * If PUK is not null, unlock SIM card with PUK and set PIN code 1203 */ unlockSim(String puk, String pin)1204 synchronized int[] unlockSim(String puk, String pin) { 1205 1206 while (mHandler == null) { 1207 try { 1208 wait(); 1209 } catch (InterruptedException e) { 1210 Thread.currentThread().interrupt(); 1211 } 1212 } 1213 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE); 1214 1215 if (puk == null) { 1216 mSimCard.supplyPin(pin, callback); 1217 } else { 1218 mSimCard.supplyPuk(puk, pin, callback); 1219 } 1220 1221 while (!mDone) { 1222 try { 1223 Log.d(LOG_TAG, "wait for done"); 1224 wait(); 1225 } catch (InterruptedException e) { 1226 // Restore the interrupted status 1227 Thread.currentThread().interrupt(); 1228 } 1229 } 1230 Log.d(LOG_TAG, "done"); 1231 int[] resultArray = new int[2]; 1232 resultArray[0] = mResult; 1233 resultArray[1] = mRetryCount; 1234 return resultArray; 1235 } 1236 } 1237 updateServiceLocation()1238 public void updateServiceLocation() { 1239 updateServiceLocationForSubscriber(getDefaultSubscription()); 1240 1241 } 1242 updateServiceLocationForSubscriber(int subId)1243 public void updateServiceLocationForSubscriber(int subId) { 1244 // No permission check needed here: this call is harmless, and it's 1245 // needed for the ServiceState.requestStateUpdate() call (which is 1246 // already intentionally exposed to 3rd parties.) 1247 final Phone phone = getPhone(subId); 1248 if (phone != null) { 1249 phone.updateServiceLocation(); 1250 } 1251 } 1252 1253 @Override isRadioOn(String callingPackage)1254 public boolean isRadioOn(String callingPackage) { 1255 return isRadioOnForSubscriber(getDefaultSubscription(), callingPackage); 1256 } 1257 1258 @Override isRadioOnForSubscriber(int subId, String callingPackage)1259 public boolean isRadioOnForSubscriber(int subId, String callingPackage) { 1260 if (!canReadPhoneState(callingPackage, "isRadioOnForSubscriber")) { 1261 return false; 1262 } 1263 return isRadioOnForSubscriber(subId); 1264 } 1265 isRadioOnForSubscriber(int subId)1266 private boolean isRadioOnForSubscriber(int subId) { 1267 final Phone phone = getPhone(subId); 1268 if (phone != null) { 1269 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF; 1270 } else { 1271 return false; 1272 } 1273 } 1274 toggleRadioOnOff()1275 public void toggleRadioOnOff() { 1276 toggleRadioOnOffForSubscriber(getDefaultSubscription()); 1277 1278 } 1279 toggleRadioOnOffForSubscriber(int subId)1280 public void toggleRadioOnOffForSubscriber(int subId) { 1281 enforceModifyPermission(); 1282 final Phone phone = getPhone(subId); 1283 if (phone != null) { 1284 phone.setRadioPower(!isRadioOnForSubscriber(subId)); 1285 } 1286 } 1287 setRadio(boolean turnOn)1288 public boolean setRadio(boolean turnOn) { 1289 return setRadioForSubscriber(getDefaultSubscription(), turnOn); 1290 } 1291 setRadioForSubscriber(int subId, boolean turnOn)1292 public boolean setRadioForSubscriber(int subId, boolean turnOn) { 1293 enforceModifyPermission(); 1294 final Phone phone = getPhone(subId); 1295 if (phone == null) { 1296 return false; 1297 } 1298 if ((phone.getServiceState().getState() != 1299 ServiceState.STATE_POWER_OFF) != turnOn) { 1300 toggleRadioOnOffForSubscriber(subId); 1301 } 1302 return true; 1303 } 1304 needMobileRadioShutdown()1305 public boolean needMobileRadioShutdown() { 1306 /* 1307 * If any of the Radios are available, it will need to be 1308 * shutdown. So return true if any Radio is available. 1309 */ 1310 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 1311 Phone phone = PhoneFactory.getPhone(i); 1312 if (phone != null && phone.isRadioAvailable()) return true; 1313 } 1314 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown."); 1315 return false; 1316 } 1317 shutdownMobileRadios()1318 public void shutdownMobileRadios() { 1319 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 1320 logv("Shutting down Phone " + i); 1321 shutdownRadioUsingPhoneId(i); 1322 } 1323 } 1324 shutdownRadioUsingPhoneId(int phoneId)1325 private void shutdownRadioUsingPhoneId(int phoneId) { 1326 enforceModifyPermission(); 1327 Phone phone = PhoneFactory.getPhone(phoneId); 1328 if (phone != null && phone.isRadioAvailable()) { 1329 phone.shutdownRadio(); 1330 } 1331 } 1332 setRadioPower(boolean turnOn)1333 public boolean setRadioPower(boolean turnOn) { 1334 return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn); 1335 } 1336 setRadioPowerForSubscriber(int subId, boolean turnOn)1337 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) { 1338 enforceModifyPermission(); 1339 final Phone phone = getPhone(subId); 1340 if (phone != null) { 1341 phone.setRadioPower(turnOn); 1342 return true; 1343 } else { 1344 return false; 1345 } 1346 } 1347 1348 // FIXME: subId version needed 1349 @Override enableDataConnectivity()1350 public boolean enableDataConnectivity() { 1351 enforceModifyPermission(); 1352 int subId = mSubscriptionController.getDefaultDataSubId(); 1353 final Phone phone = getPhone(subId); 1354 if (phone != null) { 1355 phone.setDataEnabled(true); 1356 return true; 1357 } else { 1358 return false; 1359 } 1360 } 1361 1362 // FIXME: subId version needed 1363 @Override disableDataConnectivity()1364 public boolean disableDataConnectivity() { 1365 enforceModifyPermission(); 1366 int subId = mSubscriptionController.getDefaultDataSubId(); 1367 final Phone phone = getPhone(subId); 1368 if (phone != null) { 1369 phone.setDataEnabled(false); 1370 return true; 1371 } else { 1372 return false; 1373 } 1374 } 1375 1376 // FIXME: subId version needed 1377 @Override isDataConnectivityPossible()1378 public boolean isDataConnectivityPossible() { 1379 int subId = mSubscriptionController.getDefaultDataSubId(); 1380 final Phone phone = getPhone(subId); 1381 if (phone != null) { 1382 return phone.isDataConnectivityPossible(); 1383 } else { 1384 return false; 1385 } 1386 } 1387 handlePinMmi(String dialString)1388 public boolean handlePinMmi(String dialString) { 1389 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString); 1390 } 1391 handlePinMmiForSubscriber(int subId, String dialString)1392 public boolean handlePinMmiForSubscriber(int subId, String dialString) { 1393 enforceModifyPermission(); 1394 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 1395 return false; 1396 } 1397 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId); 1398 } 1399 getCallState()1400 public int getCallState() { 1401 return getCallStateForSlot(getSlotForDefaultSubscription()); 1402 } 1403 getCallStateForSlot(int slotId)1404 public int getCallStateForSlot(int slotId) { 1405 Phone phone = PhoneFactory.getPhone(slotId); 1406 return phone == null ? TelephonyManager.CALL_STATE_IDLE : 1407 DefaultPhoneNotifier.convertCallState(phone.getState()); 1408 } 1409 1410 @Override getDataState()1411 public int getDataState() { 1412 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId()); 1413 if (phone != null) { 1414 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState()); 1415 } else { 1416 return DefaultPhoneNotifier.convertDataState(PhoneConstants.DataState.DISCONNECTED); 1417 } 1418 } 1419 1420 @Override getDataActivity()1421 public int getDataActivity() { 1422 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId()); 1423 if (phone != null) { 1424 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState()); 1425 } else { 1426 return TelephonyManager.DATA_ACTIVITY_NONE; 1427 } 1428 } 1429 1430 @Override getCellLocation(String callingPackage)1431 public Bundle getCellLocation(String callingPackage) { 1432 enforceFineOrCoarseLocationPermission("getCellLocation"); 1433 1434 // OP_COARSE_LOCATION controls both fine and coarse location. 1435 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(), 1436 callingPackage) != AppOpsManager.MODE_ALLOWED) { 1437 log("getCellLocation: returning null; mode != allowed"); 1438 return null; 1439 } 1440 1441 if (checkIfCallerIsSelfOrForegroundUser() || 1442 checkCallerInteractAcrossUsersFull()) { 1443 if (DBG_LOC) log("getCellLocation: is active user"); 1444 Bundle data = new Bundle(); 1445 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId()); 1446 if (phone == null) { 1447 return null; 1448 } 1449 phone.getCellLocation().fillInNotifierBundle(data); 1450 return data; 1451 } else { 1452 log("getCellLocation: suppress non-active user"); 1453 return null; 1454 } 1455 } 1456 enforceFineOrCoarseLocationPermission(String message)1457 private void enforceFineOrCoarseLocationPermission(String message) { 1458 try { 1459 mApp.enforceCallingOrSelfPermission( 1460 android.Manifest.permission.ACCESS_FINE_LOCATION, null); 1461 } catch (SecurityException e) { 1462 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION 1463 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this 1464 // is the weaker precondition 1465 mApp.enforceCallingOrSelfPermission( 1466 android.Manifest.permission.ACCESS_COARSE_LOCATION, message); 1467 } 1468 } 1469 1470 1471 @Override enableLocationUpdates()1472 public void enableLocationUpdates() { 1473 enableLocationUpdatesForSubscriber(getDefaultSubscription()); 1474 } 1475 1476 @Override enableLocationUpdatesForSubscriber(int subId)1477 public void enableLocationUpdatesForSubscriber(int subId) { 1478 mApp.enforceCallingOrSelfPermission( 1479 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null); 1480 final Phone phone = getPhone(subId); 1481 if (phone != null) { 1482 phone.enableLocationUpdates(); 1483 } 1484 } 1485 1486 @Override disableLocationUpdates()1487 public void disableLocationUpdates() { 1488 disableLocationUpdatesForSubscriber(getDefaultSubscription()); 1489 } 1490 1491 @Override disableLocationUpdatesForSubscriber(int subId)1492 public void disableLocationUpdatesForSubscriber(int subId) { 1493 mApp.enforceCallingOrSelfPermission( 1494 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null); 1495 final Phone phone = getPhone(subId); 1496 if (phone != null) { 1497 phone.disableLocationUpdates(); 1498 } 1499 } 1500 1501 @Override 1502 @SuppressWarnings("unchecked") getNeighboringCellInfo(String callingPackage)1503 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) { 1504 enforceFineOrCoarseLocationPermission("getNeighboringCellInfo"); 1505 1506 // OP_COARSE_LOCATION controls both fine and coarse location. 1507 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(), 1508 callingPackage) != AppOpsManager.MODE_ALLOWED) { 1509 return null; 1510 } 1511 1512 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(), 1513 callingPackage) != AppOpsManager.MODE_ALLOWED) { 1514 return null; 1515 } 1516 1517 if (checkIfCallerIsSelfOrForegroundUser() || 1518 checkCallerInteractAcrossUsersFull()) { 1519 if (DBG_LOC) log("getNeighboringCellInfo: is active user"); 1520 1521 ArrayList<NeighboringCellInfo> cells = null; 1522 1523 try { 1524 cells = (ArrayList<NeighboringCellInfo>) sendRequest( 1525 CMD_HANDLE_NEIGHBORING_CELL, null, 1526 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 1527 } catch (RuntimeException e) { 1528 Log.e(LOG_TAG, "getNeighboringCellInfo " + e); 1529 } 1530 return cells; 1531 } else { 1532 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user"); 1533 return null; 1534 } 1535 } 1536 1537 1538 @Override getAllCellInfo(String callingPackage)1539 public List<CellInfo> getAllCellInfo(String callingPackage) { 1540 enforceFineOrCoarseLocationPermission("getAllCellInfo"); 1541 1542 // OP_COARSE_LOCATION controls both fine and coarse location. 1543 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(), 1544 callingPackage) != AppOpsManager.MODE_ALLOWED) { 1545 return null; 1546 } 1547 1548 if (checkIfCallerIsSelfOrForegroundUser() || 1549 checkCallerInteractAcrossUsersFull()) { 1550 if (DBG_LOC) log("getAllCellInfo: is active user"); 1551 List<CellInfo> cellInfos = new ArrayList<CellInfo>(); 1552 for (Phone phone : PhoneFactory.getPhones()) { 1553 final List<CellInfo> info = phone.getAllCellInfo(); 1554 if (info != null) cellInfos.addAll(phone.getAllCellInfo()); 1555 } 1556 return cellInfos; 1557 } else { 1558 if (DBG_LOC) log("getAllCellInfo: suppress non-active user"); 1559 return null; 1560 } 1561 } 1562 1563 @Override setCellInfoListRate(int rateInMillis)1564 public void setCellInfoListRate(int rateInMillis) { 1565 mPhone.setCellInfoListRate(rateInMillis); 1566 } 1567 1568 @Override getImeiForSlot(int slotId, String callingPackage)1569 public String getImeiForSlot(int slotId, String callingPackage) { 1570 if (!canReadPhoneState(callingPackage, "getImeiForSlot")) { 1571 return null; 1572 } 1573 Phone phone = PhoneFactory.getPhone(slotId); 1574 return phone == null ? null : phone.getImei(); 1575 } 1576 1577 @Override getDeviceSoftwareVersionForSlot(int slotId, String callingPackage)1578 public String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage) { 1579 if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) { 1580 return null; 1581 } 1582 Phone phone = PhoneFactory.getPhone(slotId); 1583 return phone == null ? null : phone.getDeviceSvn(); 1584 } 1585 1586 // 1587 // Internal helper methods. 1588 // 1589 1590 /** 1591 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL. 1592 */ checkCallerInteractAcrossUsersFull()1593 private boolean checkCallerInteractAcrossUsersFull() { 1594 return mPhone.getContext().checkCallingOrSelfPermission( 1595 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) 1596 == PackageManager.PERMISSION_GRANTED; 1597 } 1598 checkIfCallerIsSelfOrForegroundUser()1599 private static boolean checkIfCallerIsSelfOrForegroundUser() { 1600 boolean ok; 1601 1602 boolean self = Binder.getCallingUid() == Process.myUid(); 1603 if (!self) { 1604 // Get the caller's user id then clear the calling identity 1605 // which will be restored in the finally clause. 1606 int callingUser = UserHandle.getCallingUserId(); 1607 long ident = Binder.clearCallingIdentity(); 1608 1609 try { 1610 // With calling identity cleared the current user is the foreground user. 1611 int foregroundUser = ActivityManager.getCurrentUser(); 1612 ok = (foregroundUser == callingUser); 1613 if (DBG_LOC) { 1614 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser 1615 + " callingUser=" + callingUser + " ok=" + ok); 1616 } 1617 } catch (Exception ex) { 1618 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex); 1619 ok = false; 1620 } finally { 1621 Binder.restoreCallingIdentity(ident); 1622 } 1623 } else { 1624 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self"); 1625 ok = true; 1626 } 1627 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok); 1628 return ok; 1629 } 1630 1631 /** 1632 * Make sure the caller has the MODIFY_PHONE_STATE permission. 1633 * 1634 * @throws SecurityException if the caller does not have the required permission 1635 */ enforceModifyPermission()1636 private void enforceModifyPermission() { 1637 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null); 1638 } 1639 1640 /** 1641 * Make sure either system app or the caller has carrier privilege. 1642 * 1643 * @throws SecurityException if the caller does not have the required permission/privilege 1644 */ enforceModifyPermissionOrCarrierPrivilege(int subId)1645 private void enforceModifyPermissionOrCarrierPrivilege(int subId) { 1646 int permission = mApp.checkCallingOrSelfPermission( 1647 android.Manifest.permission.MODIFY_PHONE_STATE); 1648 if (permission == PackageManager.PERMISSION_GRANTED) { 1649 return; 1650 } 1651 1652 log("No modify permission, check carrier privilege next."); 1653 enforceCarrierPrivilege(subId); 1654 } 1655 1656 /** 1657 * Make sure the caller has carrier privilege. 1658 * 1659 * @throws SecurityException if the caller does not have the required permission 1660 */ enforceCarrierPrivilege(int subId)1661 private void enforceCarrierPrivilege(int subId) { 1662 if (getCarrierPrivilegeStatus(subId) != 1663 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 1664 loge("No Carrier Privilege."); 1665 throw new SecurityException("No Carrier Privilege."); 1666 } 1667 } 1668 1669 /** 1670 * Make sure the caller has the CALL_PHONE permission. 1671 * 1672 * @throws SecurityException if the caller does not have the required permission 1673 */ enforceCallPermission()1674 private void enforceCallPermission() { 1675 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null); 1676 } 1677 enforceConnectivityInternalPermission()1678 private void enforceConnectivityInternalPermission() { 1679 mApp.enforceCallingOrSelfPermission( 1680 android.Manifest.permission.CONNECTIVITY_INTERNAL, 1681 "ConnectivityService"); 1682 } 1683 createTelUrl(String number)1684 private String createTelUrl(String number) { 1685 if (TextUtils.isEmpty(number)) { 1686 return null; 1687 } 1688 1689 return "tel:" + number; 1690 } 1691 log(String msg)1692 private static void log(String msg) { 1693 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg); 1694 } 1695 logv(String msg)1696 private static void logv(String msg) { 1697 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg); 1698 } 1699 loge(String msg)1700 private static void loge(String msg) { 1701 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg); 1702 } 1703 1704 @Override getActivePhoneType()1705 public int getActivePhoneType() { 1706 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription()); 1707 } 1708 1709 @Override getActivePhoneTypeForSlot(int slotId)1710 public int getActivePhoneTypeForSlot(int slotId) { 1711 final Phone phone = PhoneFactory.getPhone(slotId); 1712 if (phone == null) { 1713 return PhoneConstants.PHONE_TYPE_NONE; 1714 } else { 1715 return phone.getPhoneType(); 1716 } 1717 } 1718 1719 /** 1720 * Returns the CDMA ERI icon index to display 1721 */ 1722 @Override getCdmaEriIconIndex(String callingPackage)1723 public int getCdmaEriIconIndex(String callingPackage) { 1724 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage); 1725 } 1726 1727 @Override getCdmaEriIconIndexForSubscriber(int subId, String callingPackage)1728 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) { 1729 if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) { 1730 return -1; 1731 } 1732 final Phone phone = getPhone(subId); 1733 if (phone != null) { 1734 return phone.getCdmaEriIconIndex(); 1735 } else { 1736 return -1; 1737 } 1738 } 1739 1740 /** 1741 * Returns the CDMA ERI icon mode, 1742 * 0 - ON 1743 * 1 - FLASHING 1744 */ 1745 @Override getCdmaEriIconMode(String callingPackage)1746 public int getCdmaEriIconMode(String callingPackage) { 1747 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage); 1748 } 1749 1750 @Override getCdmaEriIconModeForSubscriber(int subId, String callingPackage)1751 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) { 1752 if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) { 1753 return -1; 1754 } 1755 final Phone phone = getPhone(subId); 1756 if (phone != null) { 1757 return phone.getCdmaEriIconMode(); 1758 } else { 1759 return -1; 1760 } 1761 } 1762 1763 /** 1764 * Returns the CDMA ERI text, 1765 */ 1766 @Override getCdmaEriText(String callingPackage)1767 public String getCdmaEriText(String callingPackage) { 1768 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage); 1769 } 1770 1771 @Override getCdmaEriTextForSubscriber(int subId, String callingPackage)1772 public String getCdmaEriTextForSubscriber(int subId, String callingPackage) { 1773 if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) { 1774 return null; 1775 } 1776 final Phone phone = getPhone(subId); 1777 if (phone != null) { 1778 return phone.getCdmaEriText(); 1779 } else { 1780 return null; 1781 } 1782 } 1783 1784 /** 1785 * Returns the CDMA MDN. 1786 */ 1787 @Override getCdmaMdn(int subId)1788 public String getCdmaMdn(int subId) { 1789 enforceModifyPermissionOrCarrierPrivilege(subId); 1790 final Phone phone = getPhone(subId); 1791 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) { 1792 return phone.getLine1Number(); 1793 } else { 1794 return null; 1795 } 1796 } 1797 1798 /** 1799 * Returns the CDMA MIN. 1800 */ 1801 @Override getCdmaMin(int subId)1802 public String getCdmaMin(int subId) { 1803 enforceModifyPermissionOrCarrierPrivilege(subId); 1804 final Phone phone = getPhone(subId); 1805 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { 1806 return phone.getCdmaMin(); 1807 } else { 1808 return null; 1809 } 1810 } 1811 1812 /** 1813 * Returns true if CDMA provisioning needs to run. 1814 */ needsOtaServiceProvisioning()1815 public boolean needsOtaServiceProvisioning() { 1816 return mPhone.needsOtaServiceProvisioning(); 1817 } 1818 1819 /** 1820 * Sets the voice mail number of a given subId. 1821 */ 1822 @Override setVoiceMailNumber(int subId, String alphaTag, String number)1823 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) { 1824 enforceCarrierPrivilege(subId); 1825 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER, 1826 new Pair<String, String>(alphaTag, number), new Integer(subId)); 1827 return success; 1828 } 1829 1830 /** 1831 * Returns the unread count of voicemails 1832 */ getVoiceMessageCount()1833 public int getVoiceMessageCount() { 1834 return getVoiceMessageCountForSubscriber(getDefaultSubscription()); 1835 } 1836 1837 /** 1838 * Returns the unread count of voicemails for a subId 1839 */ 1840 @Override getVoiceMessageCountForSubscriber( int subId)1841 public int getVoiceMessageCountForSubscriber( int subId) { 1842 final Phone phone = getPhone(subId); 1843 if (phone != null) { 1844 return phone.getVoiceMessageCount(); 1845 } else { 1846 return 0; 1847 } 1848 } 1849 1850 /** 1851 * Returns the data network type. 1852 * Legacy call, permission-free. 1853 * 1854 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}. 1855 */ 1856 @Override getNetworkType()1857 public int getNetworkType() { 1858 final Phone phone = getPhone(getDefaultSubscription()); 1859 if (phone != null) { 1860 return phone.getServiceState().getDataNetworkType(); 1861 } else { 1862 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1863 } 1864 } 1865 1866 /** 1867 * Returns the network type for a subId 1868 */ 1869 @Override getNetworkTypeForSubscriber(int subId, String callingPackage)1870 public int getNetworkTypeForSubscriber(int subId, String callingPackage) { 1871 if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) { 1872 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1873 } 1874 1875 final Phone phone = getPhone(subId); 1876 if (phone != null) { 1877 return phone.getServiceState().getDataNetworkType(); 1878 } else { 1879 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1880 } 1881 } 1882 1883 /** 1884 * Returns the data network type 1885 */ 1886 @Override getDataNetworkType(String callingPackage)1887 public int getDataNetworkType(String callingPackage) { 1888 return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage); 1889 } 1890 1891 /** 1892 * Returns the data network type for a subId 1893 */ 1894 @Override getDataNetworkTypeForSubscriber(int subId, String callingPackage)1895 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) { 1896 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) { 1897 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1898 } 1899 1900 final Phone phone = getPhone(subId); 1901 if (phone != null) { 1902 return phone.getServiceState().getDataNetworkType(); 1903 } else { 1904 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1905 } 1906 } 1907 1908 /** 1909 * Returns the Voice network type for a subId 1910 */ 1911 @Override getVoiceNetworkTypeForSubscriber(int subId, String callingPackage)1912 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) { 1913 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) { 1914 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1915 } 1916 1917 final Phone phone = getPhone(subId); 1918 if (phone != null) { 1919 return phone.getServiceState().getVoiceNetworkType(); 1920 } else { 1921 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 1922 } 1923 } 1924 1925 /** 1926 * @return true if a ICC card is present 1927 */ hasIccCard()1928 public boolean hasIccCard() { 1929 // FIXME Make changes to pass defaultSimId of type int 1930 return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription())); 1931 } 1932 1933 /** 1934 * @return true if a ICC card is present for a slotId 1935 */ 1936 @Override hasIccCardUsingSlotId(int slotId)1937 public boolean hasIccCardUsingSlotId(int slotId) { 1938 int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId); 1939 final Phone phone = getPhone(subId[0]); 1940 if (subId != null && phone != null) { 1941 return phone.getIccCard().hasIccCard(); 1942 } else { 1943 return false; 1944 } 1945 } 1946 1947 /** 1948 * Return if the current radio is LTE on CDMA. This 1949 * is a tri-state return value as for a period of time 1950 * the mode may be unknown. 1951 * 1952 * @param callingPackage the name of the package making the call. 1953 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE} 1954 * or {@link Phone#LTE_ON_CDMA_TRUE} 1955 */ 1956 @Override getLteOnCdmaMode(String callingPackage)1957 public int getLteOnCdmaMode(String callingPackage) { 1958 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage); 1959 } 1960 1961 @Override getLteOnCdmaModeForSubscriber(int subId, String callingPackage)1962 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) { 1963 if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) { 1964 return PhoneConstants.LTE_ON_CDMA_UNKNOWN; 1965 } 1966 1967 final Phone phone = getPhone(subId); 1968 if (phone == null) { 1969 return PhoneConstants.LTE_ON_CDMA_UNKNOWN; 1970 } else { 1971 return phone.getLteOnCdmaMode(); 1972 } 1973 } 1974 setPhone(Phone phone)1975 public void setPhone(Phone phone) { 1976 mPhone = phone; 1977 } 1978 1979 /** 1980 * {@hide} 1981 * Returns Default subId, 0 in the case of single standby. 1982 */ getDefaultSubscription()1983 private int getDefaultSubscription() { 1984 return mSubscriptionController.getDefaultSubId(); 1985 } 1986 getSlotForDefaultSubscription()1987 private int getSlotForDefaultSubscription() { 1988 return mSubscriptionController.getPhoneId(getDefaultSubscription()); 1989 } 1990 getPreferredVoiceSubscription()1991 private int getPreferredVoiceSubscription() { 1992 return mSubscriptionController.getDefaultVoiceSubId(); 1993 } 1994 1995 /** 1996 * @see android.telephony.TelephonyManager.WifiCallingChoices 1997 */ getWhenToMakeWifiCalls()1998 public int getWhenToMakeWifiCalls() { 1999 return Settings.System.getInt(mPhone.getContext().getContentResolver(), 2000 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference()); 2001 } 2002 2003 /** 2004 * @see android.telephony.TelephonyManager.WifiCallingChoices 2005 */ setWhenToMakeWifiCalls(int preference)2006 public void setWhenToMakeWifiCalls(int preference) { 2007 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference); 2008 Settings.System.putInt(mPhone.getContext().getContentResolver(), 2009 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference); 2010 } 2011 getWhenToMakeWifiCallsDefaultPreference()2012 private static int getWhenToMakeWifiCallsDefaultPreference() { 2013 // TODO: Use a build property to choose this value. 2014 return TelephonyManager.WifiCallingChoices.ALWAYS_USE; 2015 } 2016 2017 @Override iccOpenLogicalChannel(int subId, String AID)2018 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) { 2019 enforceModifyPermissionOrCarrierPrivilege(subId); 2020 2021 if (DBG) log("iccOpenLogicalChannel: subId=" + subId + " aid=" + AID); 2022 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest( 2023 CMD_OPEN_CHANNEL, AID, subId); 2024 if (DBG) log("iccOpenLogicalChannel: " + response); 2025 return response; 2026 } 2027 2028 @Override iccCloseLogicalChannel(int subId, int channel)2029 public boolean iccCloseLogicalChannel(int subId, int channel) { 2030 enforceModifyPermissionOrCarrierPrivilege(subId); 2031 2032 if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel); 2033 if (channel < 0) { 2034 return false; 2035 } 2036 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel, subId); 2037 if (DBG) log("iccCloseLogicalChannel: " + success); 2038 return success; 2039 } 2040 2041 @Override iccTransmitApduLogicalChannel(int subId, int channel, int cla, int command, int p1, int p2, int p3, String data)2042 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla, 2043 int command, int p1, int p2, int p3, String data) { 2044 enforceModifyPermissionOrCarrierPrivilege(subId); 2045 2046 if (DBG) { 2047 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel + 2048 " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + 2049 " data=" + data); 2050 } 2051 2052 if (channel < 0) { 2053 return ""; 2054 } 2055 2056 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL, 2057 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId); 2058 if (DBG) log("iccTransmitApduLogicalChannel: " + response); 2059 2060 // Append the returned status code to the end of the response payload. 2061 String s = Integer.toHexString( 2062 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1); 2063 if (response.payload != null) { 2064 s = IccUtils.bytesToHexString(response.payload) + s; 2065 } 2066 return s; 2067 } 2068 2069 @Override iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2, int p3, String data)2070 public String iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2, 2071 int p3, String data) { 2072 enforceModifyPermissionOrCarrierPrivilege(subId); 2073 2074 if (DBG) { 2075 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd=" + command 2076 + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data); 2077 } 2078 2079 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL, 2080 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId); 2081 if (DBG) log("iccTransmitApduBasicChannel: " + response); 2082 2083 // Append the returned status code to the end of the response payload. 2084 String s = Integer.toHexString( 2085 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1); 2086 if (response.payload != null) { 2087 s = IccUtils.bytesToHexString(response.payload) + s; 2088 } 2089 return s; 2090 } 2091 2092 @Override iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3, String filePath)2093 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3, 2094 String filePath) { 2095 enforceModifyPermissionOrCarrierPrivilege(subId); 2096 2097 if (DBG) { 2098 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " + 2099 p1 + " " + p2 + " " + p3 + ":" + filePath); 2100 } 2101 2102 IccIoResult response = 2103 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO, 2104 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath), 2105 subId); 2106 2107 if (DBG) { 2108 log("Exchange SIM_IO [R]" + response); 2109 } 2110 2111 byte[] result = null; 2112 int length = 2; 2113 if (response.payload != null) { 2114 length = 2 + response.payload.length; 2115 result = new byte[length]; 2116 System.arraycopy(response.payload, 0, result, 0, response.payload.length); 2117 } else { 2118 result = new byte[length]; 2119 } 2120 2121 result[length - 1] = (byte) response.sw2; 2122 result[length - 2] = (byte) response.sw1; 2123 return result; 2124 } 2125 2126 @Override sendEnvelopeWithStatus(int subId, String content)2127 public String sendEnvelopeWithStatus(int subId, String content) { 2128 enforceModifyPermissionOrCarrierPrivilege(subId); 2129 2130 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId); 2131 if (response.payload == null) { 2132 return ""; 2133 } 2134 2135 // Append the returned status code to the end of the response payload. 2136 String s = Integer.toHexString( 2137 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1); 2138 s = IccUtils.bytesToHexString(response.payload) + s; 2139 return s; 2140 } 2141 2142 /** 2143 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems} 2144 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators. 2145 * 2146 * @param itemID the ID of the item to read 2147 * @return the NV item as a String, or null on error. 2148 */ 2149 @Override nvReadItem(int itemID)2150 public String nvReadItem(int itemID) { 2151 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription()); 2152 if (DBG) log("nvReadItem: item " + itemID); 2153 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID); 2154 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"'); 2155 return value; 2156 } 2157 2158 /** 2159 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems} 2160 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators. 2161 * 2162 * @param itemID the ID of the item to read 2163 * @param itemValue the value to write, as a String 2164 * @return true on success; false on any failure 2165 */ 2166 @Override nvWriteItem(int itemID, String itemValue)2167 public boolean nvWriteItem(int itemID, String itemValue) { 2168 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription()); 2169 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"'); 2170 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM, 2171 new Pair<Integer, String>(itemID, itemValue)); 2172 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail")); 2173 return success; 2174 } 2175 2176 /** 2177 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage. 2178 * Used for device configuration by some CDMA operators. 2179 * 2180 * @param preferredRoamingList byte array containing the new PRL 2181 * @return true on success; false on any failure 2182 */ 2183 @Override nvWriteCdmaPrl(byte[] preferredRoamingList)2184 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) { 2185 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription()); 2186 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList)); 2187 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList); 2188 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail")); 2189 return success; 2190 } 2191 2192 /** 2193 * Perform the specified type of NV config reset. 2194 * Used for device configuration by some CDMA operators. 2195 * 2196 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset) 2197 * @return true on success; false on any failure 2198 */ 2199 @Override nvResetConfig(int resetType)2200 public boolean nvResetConfig(int resetType) { 2201 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription()); 2202 if (DBG) log("nvResetConfig: type " + resetType); 2203 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType); 2204 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail")); 2205 return success; 2206 } 2207 2208 /** 2209 * {@hide} 2210 * Returns Default sim, 0 in the case of single standby. 2211 */ getDefaultSim()2212 public int getDefaultSim() { 2213 //TODO Need to get it from Telephony Devcontroller 2214 return 0; 2215 } 2216 getPcscfAddress(String apnType, String callingPackage)2217 public String[] getPcscfAddress(String apnType, String callingPackage) { 2218 if (!canReadPhoneState(callingPackage, "getPcscfAddress")) { 2219 return new String[0]; 2220 } 2221 2222 2223 return mPhone.getPcscfAddress(apnType); 2224 } 2225 setImsRegistrationState(boolean registered)2226 public void setImsRegistrationState(boolean registered) { 2227 enforceModifyPermission(); 2228 mPhone.setImsRegistrationState(registered); 2229 } 2230 2231 /** 2232 * Set the network selection mode to automatic. 2233 * 2234 */ 2235 @Override setNetworkSelectionModeAutomatic(int subId)2236 public void setNetworkSelectionModeAutomatic(int subId) { 2237 enforceModifyPermissionOrCarrierPrivilege(subId); 2238 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId); 2239 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId); 2240 } 2241 2242 /** 2243 * Set the network selection mode to manual with the selected carrier. 2244 */ 2245 @Override setNetworkSelectionModeManual(int subId, OperatorInfo operator, boolean persistSelection)2246 public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator, 2247 boolean persistSelection) { 2248 enforceModifyPermissionOrCarrierPrivilege(subId); 2249 if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator); 2250 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator, 2251 persistSelection); 2252 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId); 2253 } 2254 2255 /** 2256 * Scans for available networks. 2257 */ 2258 @Override getCellNetworkScanResults(int subId)2259 public CellNetworkScanResult getCellNetworkScanResults(int subId) { 2260 enforceModifyPermissionOrCarrierPrivilege(subId); 2261 if (DBG) log("getCellNetworkScanResults: subId " + subId); 2262 CellNetworkScanResult result = (CellNetworkScanResult) sendRequest( 2263 CMD_PERFORM_NETWORK_SCAN, null, subId); 2264 return result; 2265 } 2266 2267 /** 2268 * Get the calculated preferred network type. 2269 * Used for debugging incorrect network type. 2270 * 2271 * @return the preferred network type, defined in RILConstants.java. 2272 */ 2273 @Override getCalculatedPreferredNetworkType(String callingPackage)2274 public int getCalculatedPreferredNetworkType(String callingPackage) { 2275 if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) { 2276 return RILConstants.PREFERRED_NETWORK_MODE; 2277 } 2278 2279 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere. 2280 } 2281 2282 /** 2283 * Get the preferred network type. 2284 * Used for device configuration by some CDMA operators. 2285 * 2286 * @return the preferred network type, defined in RILConstants.java. 2287 */ 2288 @Override getPreferredNetworkType(int subId)2289 public int getPreferredNetworkType(int subId) { 2290 enforceModifyPermissionOrCarrierPrivilege(subId); 2291 if (DBG) log("getPreferredNetworkType"); 2292 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId); 2293 int networkType = (result != null ? result[0] : -1); 2294 if (DBG) log("getPreferredNetworkType: " + networkType); 2295 return networkType; 2296 } 2297 2298 /** 2299 * Set the preferred network type. 2300 * Used for device configuration by some CDMA operators. 2301 * 2302 * @param networkType the preferred network type, defined in RILConstants.java. 2303 * @return true on success; false on any failure. 2304 */ 2305 @Override setPreferredNetworkType(int subId, int networkType)2306 public boolean setPreferredNetworkType(int subId, int networkType) { 2307 enforceModifyPermissionOrCarrierPrivilege(subId); 2308 if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType); 2309 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId); 2310 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail")); 2311 if (success) { 2312 Settings.Global.putInt(mPhone.getContext().getContentResolver(), 2313 Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType); 2314 } 2315 return success; 2316 } 2317 2318 /** 2319 * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning 2320 * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for 2321 * tethering. 2322 * 2323 * @return 0: Not required. 1: required. 2: Not set. 2324 * @hide 2325 */ 2326 @Override getTetherApnRequired()2327 public int getTetherApnRequired() { 2328 enforceModifyPermission(); 2329 int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(), 2330 Settings.Global.TETHER_DUN_REQUIRED, 2); 2331 // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and 2332 // config_tether_apndata. 2333 if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) { 2334 dunRequired = 1; 2335 } 2336 return dunRequired; 2337 } 2338 2339 /** 2340 * Set mobile data enabled 2341 * Used by the user through settings etc to turn on/off mobile data 2342 * 2343 * @param enable {@code true} turn turn data on, else {@code false} 2344 */ 2345 @Override setDataEnabled(int subId, boolean enable)2346 public void setDataEnabled(int subId, boolean enable) { 2347 enforceModifyPermission(); 2348 int phoneId = mSubscriptionController.getPhoneId(subId); 2349 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId); 2350 Phone phone = PhoneFactory.getPhone(phoneId); 2351 if (phone != null) { 2352 if (DBG) log("setDataEnabled: subId=" + subId + " enable=" + enable); 2353 phone.setDataEnabled(enable); 2354 } else { 2355 loge("setDataEnabled: no phone for subId=" + subId); 2356 } 2357 } 2358 2359 /** 2360 * Get whether mobile data is enabled. 2361 * 2362 * Note that this used to be available from ConnectivityService, gated by 2363 * ACCESS_NETWORK_STATE permission, so this will accept either that or 2364 * our MODIFY_PHONE_STATE. 2365 * 2366 * @return {@code true} if data is enabled else {@code false} 2367 */ 2368 @Override getDataEnabled(int subId)2369 public boolean getDataEnabled(int subId) { 2370 try { 2371 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE, 2372 null); 2373 } catch (Exception e) { 2374 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, 2375 null); 2376 } 2377 int phoneId = mSubscriptionController.getPhoneId(subId); 2378 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId); 2379 Phone phone = PhoneFactory.getPhone(phoneId); 2380 if (phone != null) { 2381 boolean retVal = phone.getDataEnabled(); 2382 if (DBG) log("getDataEnabled: subId=" + subId + " retVal=" + retVal); 2383 return retVal; 2384 } else { 2385 if (DBG) loge("getDataEnabled: no phone subId=" + subId + " retVal=false"); 2386 return false; 2387 } 2388 } 2389 2390 @Override getCarrierPrivilegeStatus(int subId)2391 public int getCarrierPrivilegeStatus(int subId) { 2392 final Phone phone = getPhone(subId); 2393 if (phone == null) { 2394 loge("getCarrierPrivilegeStatus: Invalid subId"); 2395 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 2396 } 2397 UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId()); 2398 if (card == null) { 2399 loge("getCarrierPrivilegeStatus: No UICC"); 2400 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 2401 } 2402 return card.getCarrierPrivilegeStatusForCurrentTransaction( 2403 phone.getContext().getPackageManager()); 2404 } 2405 2406 @Override checkCarrierPrivilegesForPackage(String pkgName)2407 public int checkCarrierPrivilegesForPackage(String pkgName) { 2408 if (TextUtils.isEmpty(pkgName)) 2409 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 2410 UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId()); 2411 if (card == null) { 2412 loge("checkCarrierPrivilegesForPackage: No UICC"); 2413 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 2414 } 2415 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName); 2416 } 2417 2418 @Override checkCarrierPrivilegesForPackageAnyPhone(String pkgName)2419 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) { 2420 if (TextUtils.isEmpty(pkgName)) 2421 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 2422 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 2423 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 2424 UiccCard card = UiccController.getInstance().getUiccCard(i); 2425 if (card == null) { 2426 // No UICC in that slot. 2427 continue; 2428 } 2429 2430 result = card.getCarrierPrivilegeStatus( 2431 mPhone.getContext().getPackageManager(), pkgName); 2432 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 2433 break; 2434 } 2435 } 2436 2437 return result; 2438 } 2439 2440 @Override getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId)2441 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) { 2442 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 2443 loge("phoneId " + phoneId + " is not valid."); 2444 return null; 2445 } 2446 UiccCard card = UiccController.getInstance().getUiccCard(phoneId); 2447 if (card == null) { 2448 loge("getCarrierPackageNamesForIntent: No UICC"); 2449 return null ; 2450 } 2451 return card.getCarrierPackageNamesForIntent( 2452 mPhone.getContext().getPackageManager(), intent); 2453 } 2454 2455 @Override getPackagesWithCarrierPrivileges()2456 public List<String> getPackagesWithCarrierPrivileges() { 2457 PackageManager pm = mPhone.getContext().getPackageManager(); 2458 List<String> privilegedPackages = new ArrayList<>(); 2459 List<PackageInfo> packages = null; 2460 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 2461 UiccCard card = UiccController.getInstance().getUiccCard(i); 2462 if (card == null) { 2463 // No UICC in that slot. 2464 continue; 2465 } 2466 if (card.hasCarrierPrivilegeRules()) { 2467 if (packages == null) { 2468 // Only check packages in user 0 for now 2469 packages = pm.getInstalledPackagesAsUser( 2470 PackageManager.MATCH_DISABLED_COMPONENTS 2471 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 2472 | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM); 2473 } 2474 for (int p = packages.size() - 1; p >= 0; p--) { 2475 PackageInfo pkgInfo = packages.get(p); 2476 if (pkgInfo != null && pkgInfo.packageName != null 2477 && card.getCarrierPrivilegeStatus(pkgInfo) 2478 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 2479 privilegedPackages.add(pkgInfo.packageName); 2480 } 2481 } 2482 } 2483 } 2484 return privilegedPackages; 2485 } 2486 getIccId(int subId)2487 private String getIccId(int subId) { 2488 final Phone phone = getPhone(subId); 2489 UiccCard card = phone == null ? null : phone.getUiccCard(); 2490 if (card == null) { 2491 loge("getIccId: No UICC"); 2492 return null; 2493 } 2494 String iccId = card.getIccId(); 2495 if (TextUtils.isEmpty(iccId)) { 2496 loge("getIccId: ICC ID is null or empty."); 2497 return null; 2498 } 2499 return iccId; 2500 } 2501 2502 @Override setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number)2503 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, 2504 String number) { 2505 enforceCarrierPrivilege(subId); 2506 2507 final String iccId = getIccId(subId); 2508 final Phone phone = getPhone(subId); 2509 if (phone == null) { 2510 return false; 2511 } 2512 final String subscriberId = phone.getSubscriberId(); 2513 2514 if (DBG_MERGE) { 2515 Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId=" 2516 + subscriberId + " to " + number); 2517 } 2518 2519 if (TextUtils.isEmpty(iccId)) { 2520 return false; 2521 } 2522 2523 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit(); 2524 2525 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId; 2526 if (alphaTag == null) { 2527 editor.remove(alphaTagPrefKey); 2528 } else { 2529 editor.putString(alphaTagPrefKey, alphaTag); 2530 } 2531 2532 // Record both the line number and IMSI for this ICCID, since we need to 2533 // track all merged IMSIs based on line number 2534 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId; 2535 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId; 2536 if (number == null) { 2537 editor.remove(numberPrefKey); 2538 editor.remove(subscriberPrefKey); 2539 } else { 2540 editor.putString(numberPrefKey, number); 2541 editor.putString(subscriberPrefKey, subscriberId); 2542 } 2543 2544 editor.commit(); 2545 return true; 2546 } 2547 2548 @Override getLine1NumberForDisplay(int subId, String callingPackage)2549 public String getLine1NumberForDisplay(int subId, String callingPackage) { 2550 // This is open to apps with WRITE_SMS. 2551 if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) { 2552 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission"); 2553 return null; 2554 } 2555 2556 String iccId = getIccId(subId); 2557 if (iccId != null) { 2558 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId; 2559 if (DBG_MERGE) { 2560 log("getLine1NumberForDisplay returning " + 2561 mTelephonySharedPreferences.getString(numberPrefKey, null)); 2562 } 2563 return mTelephonySharedPreferences.getString(numberPrefKey, null); 2564 } 2565 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null"); 2566 return null; 2567 } 2568 2569 @Override getLine1AlphaTagForDisplay(int subId, String callingPackage)2570 public String getLine1AlphaTagForDisplay(int subId, String callingPackage) { 2571 if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) { 2572 return null; 2573 } 2574 2575 String iccId = getIccId(subId); 2576 if (iccId != null) { 2577 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId; 2578 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null); 2579 } 2580 return null; 2581 } 2582 2583 @Override getMergedSubscriberIds(String callingPackage)2584 public String[] getMergedSubscriberIds(String callingPackage) { 2585 if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) { 2586 return null; 2587 } 2588 final Context context = mPhone.getContext(); 2589 final TelephonyManager tele = TelephonyManager.from(context); 2590 final SubscriptionManager sub = SubscriptionManager.from(context); 2591 2592 // Figure out what subscribers are currently active 2593 final ArraySet<String> activeSubscriberIds = new ArraySet<>(); 2594 // Clear calling identity, when calling TelephonyManager, because callerUid must be 2595 // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail. 2596 final long identity = Binder.clearCallingIdentity(); 2597 try { 2598 final int[] subIds = sub.getActiveSubscriptionIdList(); 2599 for (int subId : subIds) { 2600 activeSubscriberIds.add(tele.getSubscriberId(subId)); 2601 } 2602 } finally { 2603 Binder.restoreCallingIdentity(identity); 2604 } 2605 2606 // First pass, find a number override for an active subscriber 2607 String mergeNumber = null; 2608 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll(); 2609 for (String key : prefs.keySet()) { 2610 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) { 2611 final String subscriberId = (String) prefs.get(key); 2612 if (activeSubscriberIds.contains(subscriberId)) { 2613 final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length()); 2614 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId; 2615 mergeNumber = (String) prefs.get(numberKey); 2616 if (DBG_MERGE) { 2617 Slog.d(LOG_TAG, "Found line number " + mergeNumber 2618 + " for active subscriber " + subscriberId); 2619 } 2620 if (!TextUtils.isEmpty(mergeNumber)) { 2621 break; 2622 } 2623 } 2624 } 2625 } 2626 2627 // Shortcut when no active merged subscribers 2628 if (TextUtils.isEmpty(mergeNumber)) { 2629 return null; 2630 } 2631 2632 // Second pass, find all subscribers under that line override 2633 final ArraySet<String> result = new ArraySet<>(); 2634 for (String key : prefs.keySet()) { 2635 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) { 2636 final String number = (String) prefs.get(key); 2637 if (mergeNumber.equals(number)) { 2638 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length()); 2639 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId; 2640 final String subscriberId = (String) prefs.get(subscriberKey); 2641 if (!TextUtils.isEmpty(subscriberId)) { 2642 result.add(subscriberId); 2643 } 2644 } 2645 } 2646 } 2647 2648 final String[] resultArray = result.toArray(new String[result.size()]); 2649 Arrays.sort(resultArray); 2650 if (DBG_MERGE) { 2651 Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge"); 2652 } 2653 return resultArray; 2654 } 2655 2656 @Override setOperatorBrandOverride(int subId, String brand)2657 public boolean setOperatorBrandOverride(int subId, String brand) { 2658 enforceCarrierPrivilege(subId); 2659 final Phone phone = getPhone(subId); 2660 return phone == null ? false : phone.setOperatorBrandOverride(brand); 2661 } 2662 2663 @Override setRoamingOverride(int subId, List<String> gsmRoamingList, List<String> gsmNonRoamingList, List<String> cdmaRoamingList, List<String> cdmaNonRoamingList)2664 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList, 2665 List<String> gsmNonRoamingList, List<String> cdmaRoamingList, 2666 List<String> cdmaNonRoamingList) { 2667 enforceCarrierPrivilege(subId); 2668 final Phone phone = getPhone(subId); 2669 if (phone == null) { 2670 return false; 2671 } 2672 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList, 2673 cdmaNonRoamingList); 2674 } 2675 2676 @Override invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp)2677 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) { 2678 enforceModifyPermission(); 2679 2680 int returnValue = 0; 2681 try { 2682 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq); 2683 if(result.exception == null) { 2684 if (result.result != null) { 2685 byte[] responseData = (byte[])(result.result); 2686 if(responseData.length > oemResp.length) { 2687 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " + 2688 responseData.length + "bytes. Buffer Size is " + 2689 oemResp.length + "bytes."); 2690 } 2691 System.arraycopy(responseData, 0, oemResp, 0, responseData.length); 2692 returnValue = responseData.length; 2693 } 2694 } else { 2695 CommandException ex = (CommandException) result.exception; 2696 returnValue = ex.getCommandError().ordinal(); 2697 if(returnValue > 0) returnValue *= -1; 2698 } 2699 } catch (RuntimeException e) { 2700 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception"); 2701 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal()); 2702 if(returnValue > 0) returnValue *= -1; 2703 } 2704 2705 return returnValue; 2706 } 2707 2708 @Override setRadioCapability(RadioAccessFamily[] rafs)2709 public void setRadioCapability(RadioAccessFamily[] rafs) { 2710 try { 2711 ProxyController.getInstance().setRadioCapability(rafs); 2712 } catch (RuntimeException e) { 2713 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception"); 2714 } 2715 } 2716 2717 @Override getRadioAccessFamily(int phoneId, String callingPackage)2718 public int getRadioAccessFamily(int phoneId, String callingPackage) { 2719 if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) { 2720 return RadioAccessFamily.RAF_UNKNOWN; 2721 } 2722 2723 return ProxyController.getInstance().getRadioAccessFamily(phoneId); 2724 } 2725 2726 @Override enableVideoCalling(boolean enable)2727 public void enableVideoCalling(boolean enable) { 2728 enforceModifyPermission(); 2729 ImsManager.setVtSetting(mPhone.getContext(), enable); 2730 } 2731 2732 @Override isVideoCallingEnabled(String callingPackage)2733 public boolean isVideoCallingEnabled(String callingPackage) { 2734 if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) { 2735 return false; 2736 } 2737 2738 // Check the user preference and the system-level IMS setting. Even if the user has 2739 // enabled video calling, if IMS is disabled we aren't able to support video calling. 2740 // In the long run, we may instead need to check if there exists a connection service 2741 // which can support video calling. 2742 return ImsManager.isVtEnabledByPlatform(mPhone.getContext()) 2743 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext()) 2744 && ImsManager.isVtEnabledByUser(mPhone.getContext()); 2745 } 2746 2747 @Override canChangeDtmfToneLength()2748 public boolean canChangeDtmfToneLength() { 2749 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL); 2750 } 2751 2752 @Override isWorldPhone()2753 public boolean isWorldPhone() { 2754 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL); 2755 } 2756 2757 @Override isTtyModeSupported()2758 public boolean isTtyModeSupported() { 2759 TelecomManager telecomManager = TelecomManager.from(mPhone.getContext()); 2760 TelephonyManager telephonyManager = 2761 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE); 2762 return !telephonyManager.isMultiSimEnabled() && telecomManager.isTtySupported(); 2763 } 2764 2765 @Override isHearingAidCompatibilitySupported()2766 public boolean isHearingAidCompatibilitySupported() { 2767 return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled); 2768 } 2769 2770 /** 2771 * Returns the unique device ID of phone, for example, the IMEI for 2772 * GSM and the MEID for CDMA phones. Return null if device ID is not available. 2773 * 2774 * <p>Requires Permission: 2775 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 2776 */ 2777 @Override getDeviceId(String callingPackage)2778 public String getDeviceId(String callingPackage) { 2779 if (!canReadPhoneState(callingPackage, "getDeviceId")) { 2780 return null; 2781 } 2782 2783 final Phone phone = PhoneFactory.getPhone(0); 2784 if (phone != null) { 2785 return phone.getDeviceId(); 2786 } else { 2787 return null; 2788 } 2789 } 2790 2791 /* 2792 * {@hide} 2793 * Returns the IMS Registration Status 2794 */ 2795 @Override isImsRegistered()2796 public boolean isImsRegistered() { 2797 return mPhone.isImsRegistered(); 2798 } 2799 2800 @Override getSubIdForPhoneAccount(PhoneAccount phoneAccount)2801 public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) { 2802 return PhoneUtils.getSubIdForPhoneAccount(phoneAccount); 2803 } 2804 2805 /* 2806 * {@hide} 2807 * Returns the IMS Registration Status 2808 */ isWifiCallingAvailable()2809 public boolean isWifiCallingAvailable() { 2810 return mPhone.isWifiCallingEnabled(); 2811 } 2812 2813 /* 2814 * {@hide} 2815 * Returns the IMS Registration Status 2816 */ isVolteAvailable()2817 public boolean isVolteAvailable() { 2818 return mPhone.isVolteEnabled(); 2819 } 2820 2821 /* 2822 * {@hide} Returns the IMS Registration Status 2823 */ isVideoTelephonyAvailable()2824 public boolean isVideoTelephonyAvailable() { 2825 return mPhone.isVideoEnabled(); 2826 } 2827 canReadPhoneState(String callingPackage, String message)2828 private boolean canReadPhoneState(String callingPackage, String message) { 2829 try { 2830 mApp.enforceCallingOrSelfPermission( 2831 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message); 2832 2833 // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission 2834 return true; 2835 } catch (SecurityException e) { 2836 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, 2837 message); 2838 } 2839 2840 if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), 2841 callingPackage) != AppOpsManager.MODE_ALLOWED) { 2842 return false; 2843 } 2844 2845 return true; 2846 } 2847 2848 /** 2849 * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers. 2850 */ canReadPhoneNumber(String callingPackage, String message)2851 private boolean canReadPhoneNumber(String callingPackage, String message) { 2852 // Default SMS app can always read it. 2853 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS, 2854 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) { 2855 return true; 2856 } 2857 try { 2858 return canReadPhoneState(callingPackage, message); 2859 } catch (SecurityException readPhoneStateSecurityException) { 2860 try { 2861 // Can be read with READ_SMS too. 2862 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message); 2863 return mAppOps.noteOp(AppOpsManager.OP_READ_SMS, 2864 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED; 2865 } catch (SecurityException readSmsSecurityException) { 2866 // Throw exception with message including both READ_PHONE_STATE and READ_SMS 2867 // permissions 2868 throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() + 2869 " nor current process has " + android.Manifest.permission.READ_PHONE_STATE + 2870 " or " + android.Manifest.permission.READ_SMS + "."); 2871 } 2872 } 2873 } 2874 2875 @Override factoryReset(int subId)2876 public void factoryReset(int subId) { 2877 enforceConnectivityInternalPermission(); 2878 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { 2879 return; 2880 } 2881 2882 final long identity = Binder.clearCallingIdentity(); 2883 try { 2884 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction( 2885 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) { 2886 // Enable data 2887 setDataEnabled(subId, true); 2888 // Set network selection mode to automatic 2889 setNetworkSelectionModeAutomatic(subId); 2890 // Set preferred mobile network type to the best available 2891 setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE); 2892 // Turn off roaming 2893 SubscriptionManager.from(mApp).setDataRoaming(0, subId); 2894 } 2895 } finally { 2896 Binder.restoreCallingIdentity(identity); 2897 } 2898 } 2899 2900 @Override getLocaleFromDefaultSim()2901 public String getLocaleFromDefaultSim() { 2902 // We query all subscriptions instead of just the active ones, because 2903 // this might be called early on in the provisioning flow when the 2904 // subscriptions potentially aren't active yet. 2905 final List<SubscriptionInfo> slist = getAllSubscriptionInfoList(); 2906 if (slist == null || slist.isEmpty()) { 2907 return null; 2908 } 2909 2910 // This function may be called very early, say, from the setup wizard, at 2911 // which point we won't have a default subscription set. If that's the case 2912 // we just choose the first, which will be valid in "most cases". 2913 final int defaultSubId = getDefaultSubscription(); 2914 SubscriptionInfo info = null; 2915 if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 2916 info = slist.get(0); 2917 } else { 2918 for (SubscriptionInfo item : slist) { 2919 if (item.getSubscriptionId() == defaultSubId) { 2920 info = item; 2921 break; 2922 } 2923 } 2924 2925 if (info == null) { 2926 return null; 2927 } 2928 } 2929 2930 // Try and fetch the locale from the carrier properties or from the SIM language 2931 // preferences (EF-PL and EF-LI)... 2932 final int mcc = info.getMcc(); 2933 final Phone defaultPhone = getPhone(info.getSubscriptionId()); 2934 String simLanguage = null; 2935 if (defaultPhone != null) { 2936 final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs(); 2937 if (localeFromDefaultSim != null) { 2938 if (!localeFromDefaultSim.getCountry().isEmpty()) { 2939 if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim); 2940 return localeFromDefaultSim.toLanguageTag(); 2941 } else { 2942 simLanguage = localeFromDefaultSim.getLanguage(); 2943 } 2944 } 2945 } 2946 2947 // The SIM language preferences only store a language (e.g. fr = French), not an 2948 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from 2949 // the SIM and carrier preferences does not include a country we add the country 2950 // determined from the SIM MCC to provide an exact locale. 2951 final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage); 2952 if (mccLocale != null) { 2953 if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale); 2954 return mccLocale.toLanguageTag(); 2955 } 2956 2957 if (DBG) log("No locale found - returning null"); 2958 return null; 2959 } 2960 getAllSubscriptionInfoList()2961 private List<SubscriptionInfo> getAllSubscriptionInfoList() { 2962 final long identity = Binder.clearCallingIdentity(); 2963 try { 2964 return mSubscriptionController.getAllSubInfoList( 2965 mPhone.getContext().getOpPackageName()); 2966 } finally { 2967 Binder.restoreCallingIdentity(identity); 2968 } 2969 } 2970 getActiveSubscriptionInfoList()2971 private List<SubscriptionInfo> getActiveSubscriptionInfoList() { 2972 final long identity = Binder.clearCallingIdentity(); 2973 try { 2974 return mSubscriptionController.getActiveSubscriptionInfoList( 2975 mPhone.getContext().getOpPackageName()); 2976 } finally { 2977 Binder.restoreCallingIdentity(identity); 2978 } 2979 } 2980 2981 /** 2982 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object 2983 * representing the state of the modem. 2984 * 2985 * NOTE: This clears the modem state, so there should only every be one caller. 2986 * @hide 2987 */ 2988 @Override requestModemActivityInfo(ResultReceiver result)2989 public void requestModemActivityInfo(ResultReceiver result) { 2990 enforceModifyPermission(); 2991 2992 ModemActivityInfo info = (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null); 2993 Bundle bundle = new Bundle(); 2994 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, info); 2995 result.send(0, bundle); 2996 } 2997 2998 /** 2999 * {@hide} 3000 * Returns the service state information on specified subscription. 3001 */ 3002 @Override getServiceStateForSubscriber(int subId, String callingPackage)3003 public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) { 3004 3005 if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) { 3006 return null; 3007 } 3008 3009 final Phone phone = getPhone(subId); 3010 if (phone == null) { 3011 return null; 3012 } 3013 3014 return phone.getServiceState(); 3015 } 3016 3017 /** 3018 * Returns the URI for the per-account voicemail ringtone set in Phone settings. 3019 * 3020 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the 3021 * voicemail ringtone. 3022 * @return The URI for the ringtone to play when receiving a voicemail from a specific 3023 * PhoneAccount. 3024 */ 3025 @Override getVoicemailRingtoneUri(PhoneAccountHandle accountHandle)3026 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) { 3027 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle); 3028 if (phone == null) { 3029 return null; 3030 } 3031 3032 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone); 3033 } 3034 3035 /** 3036 * Returns whether vibration is set for voicemail notification in Phone settings. 3037 * 3038 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the 3039 * voicemail vibration setting. 3040 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise. 3041 */ 3042 @Override isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle)3043 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) { 3044 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle); 3045 if (phone == null) { 3046 return false; 3047 } 3048 3049 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone); 3050 } 3051 3052 } 3053