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