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