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