1 /* 2 * Copyright (C) 2007 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 17 package com.android.server; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.net.LinkCapabilities; 23 import android.net.LinkProperties; 24 import android.os.Binder; 25 import android.os.Bundle; 26 import android.os.IBinder; 27 import android.os.RemoteException; 28 import android.telephony.CellLocation; 29 import android.telephony.PhoneStateListener; 30 import android.telephony.ServiceState; 31 import android.telephony.SignalStrength; 32 import android.telephony.CellInfo; 33 import android.telephony.TelephonyManager; 34 import android.text.TextUtils; 35 import android.util.Slog; 36 37 import java.util.ArrayList; 38 import java.io.FileDescriptor; 39 import java.io.PrintWriter; 40 import java.net.NetworkInterface; 41 42 import com.android.internal.app.IBatteryStats; 43 import com.android.internal.telephony.ITelephonyRegistry; 44 import com.android.internal.telephony.IPhoneStateListener; 45 import com.android.internal.telephony.DefaultPhoneNotifier; 46 import com.android.internal.telephony.Phone; 47 import com.android.internal.telephony.ServiceStateTracker; 48 import com.android.internal.telephony.TelephonyIntents; 49 import com.android.server.am.BatteryStatsService; 50 51 /** 52 * Since phone process can be restarted, this class provides a centralized place 53 * that applications can register and be called back from. 54 */ 55 class TelephonyRegistry extends ITelephonyRegistry.Stub { 56 private static final String TAG = "TelephonyRegistry"; 57 private static final boolean DBG = false; 58 59 private static class Record { 60 String pkgForDebug; 61 62 IBinder binder; 63 64 IPhoneStateListener callback; 65 66 int events; 67 } 68 69 private final Context mContext; 70 71 // access should be inside synchronized (mRecords) for these two fields 72 private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>(); 73 private final ArrayList<Record> mRecords = new ArrayList<Record>(); 74 75 private final IBatteryStats mBatteryStats; 76 77 private int mCallState = TelephonyManager.CALL_STATE_IDLE; 78 79 private String mCallIncomingNumber = ""; 80 81 private ServiceState mServiceState = new ServiceState(); 82 83 private SignalStrength mSignalStrength = new SignalStrength(); 84 85 private boolean mMessageWaiting = false; 86 87 private boolean mCallForwarding = false; 88 89 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 90 91 private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN; 92 93 private boolean mDataConnectionPossible = false; 94 95 private String mDataConnectionReason = ""; 96 97 private String mDataConnectionApn = ""; 98 99 private ArrayList<String> mConnectedApns; 100 101 private LinkProperties mDataConnectionLinkProperties; 102 103 private LinkCapabilities mDataConnectionLinkCapabilities; 104 105 private Bundle mCellLocation = new Bundle(); 106 107 private int mDataConnectionNetworkType; 108 109 private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN; 110 111 private CellInfo mCellInfo = null; 112 113 static final int PHONE_STATE_PERMISSION_MASK = 114 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | 115 PhoneStateListener.LISTEN_CALL_STATE | 116 PhoneStateListener.LISTEN_DATA_ACTIVITY | 117 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | 118 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR; 119 120 // we keep a copy of all of the state so we can send it out when folks 121 // register for it 122 // 123 // In these calls we call with the lock held. This is safe becasuse remote 124 // calls go through a oneway interface and local calls going through a 125 // handler before they get to app code. 126 127 TelephonyRegistry(Context context) { 128 CellLocation location = CellLocation.getEmpty(); 129 130 // Note that location can be null for non-phone builds like 131 // like the generic one. 132 if (location != null) { 133 location.fillInNotifierBundle(mCellLocation); 134 } 135 mContext = context; 136 mBatteryStats = BatteryStatsService.getService(); 137 mConnectedApns = new ArrayList<String>(); 138 } 139 140 public void listen(String pkgForDebug, IPhoneStateListener callback, int events, 141 boolean notifyNow) { 142 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" + 143 // Integer.toHexString(events)); 144 if (events != 0) { 145 /* Checks permission and throws Security exception */ 146 checkListenerPermission(events); 147 148 synchronized (mRecords) { 149 // register 150 Record r = null; 151 find_and_add: { 152 IBinder b = callback.asBinder(); 153 final int N = mRecords.size(); 154 for (int i = 0; i < N; i++) { 155 r = mRecords.get(i); 156 if (b == r.binder) { 157 break find_and_add; 158 } 159 } 160 r = new Record(); 161 r.binder = b; 162 r.callback = callback; 163 r.pkgForDebug = pkgForDebug; 164 mRecords.add(r); 165 } 166 int send = events & (events ^ r.events); 167 r.events = events; 168 if (notifyNow) { 169 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { 170 try { 171 r.callback.onServiceStateChanged(new ServiceState(mServiceState)); 172 } catch (RemoteException ex) { 173 remove(r.binder); 174 } 175 } 176 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { 177 try { 178 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength(); 179 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 180 : gsmSignalStrength)); 181 } catch (RemoteException ex) { 182 remove(r.binder); 183 } 184 } 185 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { 186 try { 187 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting); 188 } catch (RemoteException ex) { 189 remove(r.binder); 190 } 191 } 192 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { 193 try { 194 r.callback.onCallForwardingIndicatorChanged(mCallForwarding); 195 } catch (RemoteException ex) { 196 remove(r.binder); 197 } 198 } 199 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { 200 try { 201 r.callback.onCellLocationChanged(new Bundle(mCellLocation)); 202 } catch (RemoteException ex) { 203 remove(r.binder); 204 } 205 } 206 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { 207 try { 208 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber); 209 } catch (RemoteException ex) { 210 remove(r.binder); 211 } 212 } 213 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { 214 try { 215 r.callback.onDataConnectionStateChanged(mDataConnectionState, 216 mDataConnectionNetworkType); 217 } catch (RemoteException ex) { 218 remove(r.binder); 219 } 220 } 221 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { 222 try { 223 r.callback.onDataActivity(mDataActivity); 224 } catch (RemoteException ex) { 225 remove(r.binder); 226 } 227 } 228 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { 229 try { 230 r.callback.onSignalStrengthsChanged(mSignalStrength); 231 } catch (RemoteException ex) { 232 remove(r.binder); 233 } 234 } 235 if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { 236 try { 237 r.callback.onOtaspChanged(mOtaspMode); 238 } catch (RemoteException ex) { 239 remove(r.binder); 240 } 241 } 242 if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { 243 try { 244 r.callback.onCellInfoChanged(new CellInfo(mCellInfo)); 245 } catch (RemoteException ex) { 246 remove(r.binder); 247 } 248 } 249 } 250 } 251 } else { 252 remove(callback.asBinder()); 253 } 254 } 255 256 private void remove(IBinder binder) { 257 synchronized (mRecords) { 258 final int recordCount = mRecords.size(); 259 for (int i = 0; i < recordCount; i++) { 260 if (mRecords.get(i).binder == binder) { 261 mRecords.remove(i); 262 return; 263 } 264 } 265 } 266 } 267 268 public void notifyCallState(int state, String incomingNumber) { 269 if (!checkNotifyPermission("notifyCallState()")) { 270 return; 271 } 272 synchronized (mRecords) { 273 mCallState = state; 274 mCallIncomingNumber = incomingNumber; 275 for (Record r : mRecords) { 276 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { 277 try { 278 r.callback.onCallStateChanged(state, incomingNumber); 279 } catch (RemoteException ex) { 280 mRemoveList.add(r.binder); 281 } 282 } 283 } 284 handleRemoveListLocked(); 285 } 286 broadcastCallStateChanged(state, incomingNumber); 287 } 288 289 public void notifyServiceState(ServiceState state) { 290 if (!checkNotifyPermission("notifyServiceState()")){ 291 return; 292 } 293 synchronized (mRecords) { 294 mServiceState = state; 295 for (Record r : mRecords) { 296 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { 297 try { 298 r.callback.onServiceStateChanged(new ServiceState(state)); 299 } catch (RemoteException ex) { 300 mRemoveList.add(r.binder); 301 } 302 } 303 } 304 handleRemoveListLocked(); 305 } 306 broadcastServiceStateChanged(state); 307 } 308 309 public void notifySignalStrength(SignalStrength signalStrength) { 310 if (!checkNotifyPermission("notifySignalStrength()")) { 311 return; 312 } 313 synchronized (mRecords) { 314 mSignalStrength = signalStrength; 315 for (Record r : mRecords) { 316 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { 317 try { 318 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength)); 319 } catch (RemoteException ex) { 320 mRemoveList.add(r.binder); 321 } 322 } 323 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { 324 try { 325 int gsmSignalStrength = signalStrength.getGsmSignalStrength(); 326 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 327 : gsmSignalStrength)); 328 } catch (RemoteException ex) { 329 mRemoveList.add(r.binder); 330 } 331 } 332 } 333 handleRemoveListLocked(); 334 } 335 broadcastSignalStrengthChanged(signalStrength); 336 } 337 338 public void notifyCellInfo(CellInfo cellInfo) { 339 if (!checkNotifyPermission("notifyCellInfo()")) { 340 return; 341 } 342 343 synchronized (mRecords) { 344 mCellInfo = cellInfo; 345 for (Record r : mRecords) { 346 if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { 347 try { 348 r.callback.onCellInfoChanged(new CellInfo(cellInfo)); 349 } catch (RemoteException ex) { 350 mRemoveList.add(r.binder); 351 } 352 } 353 } 354 handleRemoveListLocked(); 355 } 356 } 357 358 public void notifyMessageWaitingChanged(boolean mwi) { 359 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { 360 return; 361 } 362 synchronized (mRecords) { 363 mMessageWaiting = mwi; 364 for (Record r : mRecords) { 365 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { 366 try { 367 r.callback.onMessageWaitingIndicatorChanged(mwi); 368 } catch (RemoteException ex) { 369 mRemoveList.add(r.binder); 370 } 371 } 372 } 373 handleRemoveListLocked(); 374 } 375 } 376 377 public void notifyCallForwardingChanged(boolean cfi) { 378 if (!checkNotifyPermission("notifyCallForwardingChanged()")) { 379 return; 380 } 381 synchronized (mRecords) { 382 mCallForwarding = cfi; 383 for (Record r : mRecords) { 384 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { 385 try { 386 r.callback.onCallForwardingIndicatorChanged(cfi); 387 } catch (RemoteException ex) { 388 mRemoveList.add(r.binder); 389 } 390 } 391 } 392 handleRemoveListLocked(); 393 } 394 } 395 396 public void notifyDataActivity(int state) { 397 if (!checkNotifyPermission("notifyDataActivity()" )) { 398 return; 399 } 400 synchronized (mRecords) { 401 mDataActivity = state; 402 for (Record r : mRecords) { 403 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { 404 try { 405 r.callback.onDataActivity(state); 406 } catch (RemoteException ex) { 407 mRemoveList.add(r.binder); 408 } 409 } 410 } 411 handleRemoveListLocked(); 412 } 413 } 414 415 public void notifyDataConnection(int state, boolean isDataConnectivityPossible, 416 String reason, String apn, String apnType, LinkProperties linkProperties, 417 LinkCapabilities linkCapabilities, int networkType, boolean roaming) { 418 if (!checkNotifyPermission("notifyDataConnection()" )) { 419 return; 420 } 421 if (DBG) { 422 Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" 423 + isDataConnectivityPossible + " reason='" + reason 424 + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType); 425 } 426 synchronized (mRecords) { 427 boolean modified = false; 428 if (state == TelephonyManager.DATA_CONNECTED) { 429 if (!mConnectedApns.contains(apnType)) { 430 mConnectedApns.add(apnType); 431 if (mDataConnectionState != state) { 432 mDataConnectionState = state; 433 modified = true; 434 } 435 } 436 } else { 437 if (mConnectedApns.remove(apnType)) { 438 if (mConnectedApns.isEmpty()) { 439 mDataConnectionState = state; 440 modified = true; 441 } else { 442 // leave mDataConnectionState as is and 443 // send out the new status for the APN in question. 444 } 445 } 446 } 447 mDataConnectionPossible = isDataConnectivityPossible; 448 mDataConnectionReason = reason; 449 mDataConnectionLinkProperties = linkProperties; 450 mDataConnectionLinkCapabilities = linkCapabilities; 451 if (mDataConnectionNetworkType != networkType) { 452 mDataConnectionNetworkType = networkType; 453 // need to tell registered listeners about the new network type 454 modified = true; 455 } 456 if (modified) { 457 if (DBG) { 458 Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState 459 + ", " + mDataConnectionNetworkType + ")"); 460 } 461 for (Record r : mRecords) { 462 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { 463 try { 464 r.callback.onDataConnectionStateChanged(mDataConnectionState, 465 mDataConnectionNetworkType); 466 } catch (RemoteException ex) { 467 mRemoveList.add(r.binder); 468 } 469 } 470 } 471 handleRemoveListLocked(); 472 } 473 } 474 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, 475 apnType, linkProperties, linkCapabilities, roaming); 476 } 477 478 public void notifyDataConnectionFailed(String reason, String apnType) { 479 if (!checkNotifyPermission("notifyDataConnectionFailed()")) { 480 return; 481 } 482 /* 483 * This is commented out because there is no onDataConnectionFailed callback 484 * in PhoneStateListener. There should be. 485 synchronized (mRecords) { 486 mDataConnectionFailedReason = reason; 487 final int N = mRecords.size(); 488 for (int i=N-1; i>=0; i--) { 489 Record r = mRecords.get(i); 490 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) { 491 // XXX 492 } 493 } 494 } 495 */ 496 broadcastDataConnectionFailed(reason, apnType); 497 } 498 499 public void notifyCellLocation(Bundle cellLocation) { 500 if (!checkNotifyPermission("notifyCellLocation()")) { 501 return; 502 } 503 synchronized (mRecords) { 504 mCellLocation = cellLocation; 505 for (Record r : mRecords) { 506 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { 507 try { 508 r.callback.onCellLocationChanged(new Bundle(cellLocation)); 509 } catch (RemoteException ex) { 510 mRemoveList.add(r.binder); 511 } 512 513 } 514 } 515 handleRemoveListLocked(); 516 } 517 } 518 519 public void notifyOtaspChanged(int otaspMode) { 520 if (!checkNotifyPermission("notifyOtaspChanged()" )) { 521 return; 522 } 523 synchronized (mRecords) { 524 mOtaspMode = otaspMode; 525 for (Record r : mRecords) { 526 if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { 527 try { 528 r.callback.onOtaspChanged(otaspMode); 529 } catch (RemoteException ex) { 530 mRemoveList.add(r.binder); 531 } 532 } 533 } 534 handleRemoveListLocked(); 535 } 536 } 537 538 @Override 539 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 540 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 541 != PackageManager.PERMISSION_GRANTED) { 542 pw.println("Permission Denial: can't dump telephony.registry from from pid=" 543 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 544 return; 545 } 546 synchronized (mRecords) { 547 final int recordCount = mRecords.size(); 548 pw.println("last known state:"); 549 pw.println(" mCallState=" + mCallState); 550 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber); 551 pw.println(" mServiceState=" + mServiceState); 552 pw.println(" mSignalStrength=" + mSignalStrength); 553 pw.println(" mMessageWaiting=" + mMessageWaiting); 554 pw.println(" mCallForwarding=" + mCallForwarding); 555 pw.println(" mDataActivity=" + mDataActivity); 556 pw.println(" mDataConnectionState=" + mDataConnectionState); 557 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible); 558 pw.println(" mDataConnectionReason=" + mDataConnectionReason); 559 pw.println(" mDataConnectionApn=" + mDataConnectionApn); 560 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties); 561 pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities); 562 pw.println(" mCellLocation=" + mCellLocation); 563 pw.println(" mCellInfo=" + mCellInfo); 564 pw.println("registrations: count=" + recordCount); 565 for (Record r : mRecords) { 566 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); 567 } 568 } 569 } 570 571 // 572 // the legacy intent broadcasting 573 // 574 575 private void broadcastServiceStateChanged(ServiceState state) { 576 long ident = Binder.clearCallingIdentity(); 577 try { 578 mBatteryStats.notePhoneState(state.getState()); 579 } catch (RemoteException re) { 580 // Can't do much 581 } finally { 582 Binder.restoreCallingIdentity(ident); 583 } 584 585 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 586 Bundle data = new Bundle(); 587 state.fillInNotifierBundle(data); 588 intent.putExtras(data); 589 mContext.sendStickyBroadcast(intent); 590 } 591 592 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) { 593 long ident = Binder.clearCallingIdentity(); 594 try { 595 mBatteryStats.notePhoneSignalStrength(signalStrength); 596 } catch (RemoteException e) { 597 /* The remote entity disappeared, we can safely ignore the exception. */ 598 } finally { 599 Binder.restoreCallingIdentity(ident); 600 } 601 602 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); 603 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 604 Bundle data = new Bundle(); 605 signalStrength.fillInNotifierBundle(data); 606 intent.putExtras(data); 607 mContext.sendStickyBroadcast(intent); 608 } 609 610 private void broadcastCallStateChanged(int state, String incomingNumber) { 611 long ident = Binder.clearCallingIdentity(); 612 try { 613 if (state == TelephonyManager.CALL_STATE_IDLE) { 614 mBatteryStats.notePhoneOff(); 615 } else { 616 mBatteryStats.notePhoneOn(); 617 } 618 } catch (RemoteException e) { 619 /* The remote entity disappeared, we can safely ignore the exception. */ 620 } finally { 621 Binder.restoreCallingIdentity(ident); 622 } 623 624 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED); 625 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString()); 626 if (!TextUtils.isEmpty(incomingNumber)) { 627 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); 628 } 629 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE); 630 } 631 632 private void broadcastDataConnectionStateChanged(int state, 633 boolean isDataConnectivityPossible, 634 String reason, String apn, String apnType, LinkProperties linkProperties, 635 LinkCapabilities linkCapabilities, boolean roaming) { 636 // Note: not reporting to the battery stats service here, because the 637 // status bar takes care of that after taking into account all of the 638 // required info. 639 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); 640 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString()); 641 if (!isDataConnectivityPossible) { 642 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true); 643 } 644 if (reason != null) { 645 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason); 646 } 647 if (linkProperties != null) { 648 intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties); 649 String iface = linkProperties.getInterfaceName(); 650 if (iface != null) { 651 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface); 652 } 653 } 654 if (linkCapabilities != null) { 655 intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities); 656 } 657 if (roaming) intent.putExtra(Phone.DATA_NETWORK_ROAMING_KEY, true); 658 659 intent.putExtra(Phone.DATA_APN_KEY, apn); 660 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType); 661 mContext.sendStickyBroadcast(intent); 662 } 663 664 private void broadcastDataConnectionFailed(String reason, String apnType) { 665 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); 666 intent.putExtra(Phone.FAILURE_REASON_KEY, reason); 667 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType); 668 mContext.sendStickyBroadcast(intent); 669 } 670 671 private boolean checkNotifyPermission(String method) { 672 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 673 == PackageManager.PERMISSION_GRANTED) { 674 return true; 675 } 676 String msg = "Modify Phone State Permission Denial: " + method + " from pid=" 677 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid(); 678 if (DBG) Slog.w(TAG, msg); 679 return false; 680 } 681 682 private void checkListenerPermission(int events) { 683 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { 684 mContext.enforceCallingOrSelfPermission( 685 android.Manifest.permission.ACCESS_COARSE_LOCATION, null); 686 687 } 688 689 if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { 690 mContext.enforceCallingOrSelfPermission( 691 android.Manifest.permission.ACCESS_COARSE_LOCATION, null); 692 693 } 694 695 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) { 696 mContext.enforceCallingOrSelfPermission( 697 android.Manifest.permission.READ_PHONE_STATE, null); 698 } 699 } 700 701 private void handleRemoveListLocked() { 702 if (mRemoveList.size() > 0) { 703 for (IBinder b: mRemoveList) { 704 remove(b); 705 } 706 mRemoveList.clear(); 707 } 708 } 709 } 710