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