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