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