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