TelephonyRegistry.java revision f9cb86aebe9647e0fe0137fc198ba16c017445c6
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 17package com.android.server; 18 19import android.app.ActivityManager; 20import android.content.BroadcastReceiver; 21import android.content.Context; 22import android.content.Intent; 23import android.content.IntentFilter; 24import android.content.pm.PackageManager; 25import android.net.LinkProperties; 26import android.net.NetworkCapabilities; 27import android.os.Binder; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.Message; 32import android.os.RemoteException; 33import android.os.UserHandle; 34import android.telephony.CellLocation; 35import android.telephony.DataConnectionRealTimeInfo; 36import android.telephony.PhoneStateListener; 37import android.telephony.ServiceState; 38import android.telephony.SignalStrength; 39import android.telephony.CellInfo; 40import android.telephony.TelephonyManager; 41import android.telephony.DisconnectCause; 42import android.telephony.PreciseCallState; 43import android.telephony.PreciseDataConnectionState; 44import android.telephony.PreciseDisconnectCause; 45import android.text.TextUtils; 46import android.util.Slog; 47 48import java.util.ArrayList; 49import java.util.List; 50import java.io.FileDescriptor; 51import java.io.PrintWriter; 52 53import com.android.internal.app.IBatteryStats; 54import com.android.internal.telephony.ITelephonyRegistry; 55import com.android.internal.telephony.IPhoneStateListener; 56import com.android.internal.telephony.DefaultPhoneNotifier; 57import com.android.internal.telephony.PhoneConstants; 58import com.android.internal.telephony.ServiceStateTracker; 59import com.android.internal.telephony.TelephonyIntents; 60import com.android.server.am.BatteryStatsService; 61 62/** 63 * Since phone process can be restarted, this class provides a centralized place 64 * that applications can register and be called back from. 65 */ 66class TelephonyRegistry extends ITelephonyRegistry.Stub { 67 private static final String TAG = "TelephonyRegistry"; 68 private static final boolean DBG = false; 69 private static final boolean DBG_LOC = false; 70 71 private static class Record { 72 String pkgForDebug; 73 74 IBinder binder; 75 76 IPhoneStateListener callback; 77 78 int callerUid; 79 80 int events; 81 82 @Override 83 public String toString() { 84 return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid + 85 " events=" + Integer.toHexString(events) + "}"; 86 } 87 } 88 89 private final Context mContext; 90 91 // access should be inside synchronized (mRecords) for these two fields 92 private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>(); 93 private final ArrayList<Record> mRecords = new ArrayList<Record>(); 94 95 private final IBatteryStats mBatteryStats; 96 97 private int mCallState = TelephonyManager.CALL_STATE_IDLE; 98 99 private String mCallIncomingNumber = ""; 100 101 private ServiceState mServiceState = new ServiceState(); 102 103 private SignalStrength mSignalStrength = new SignalStrength(); 104 105 private boolean mMessageWaiting = false; 106 107 private boolean mCallForwarding = false; 108 109 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 110 111 private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN; 112 113 private boolean mDataConnectionPossible = false; 114 115 private String mDataConnectionReason = ""; 116 117 private String mDataConnectionApn = ""; 118 119 private ArrayList<String> mConnectedApns; 120 121 private LinkProperties mDataConnectionLinkProperties; 122 123 private NetworkCapabilities mDataConnectionNetworkCapabilities; 124 125 private Bundle mCellLocation = new Bundle(); 126 127 private int mDataConnectionNetworkType; 128 129 private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN; 130 131 private List<CellInfo> mCellInfo = null; 132 133 private DataConnectionRealTimeInfo mDcRtInfo = new DataConnectionRealTimeInfo(); 134 135 private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE; 136 137 private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE; 138 139 private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE; 140 141 private PreciseCallState mPreciseCallState = new PreciseCallState(); 142 143 private PreciseDataConnectionState mPreciseDataConnectionState = 144 new PreciseDataConnectionState(); 145 146 static final int PHONE_STATE_PERMISSION_MASK = 147 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | 148 PhoneStateListener.LISTEN_CALL_STATE | 149 PhoneStateListener.LISTEN_DATA_ACTIVITY | 150 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | 151 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR; 152 153 static final int PRECISE_PHONE_STATE_PERMISSION_MASK = 154 PhoneStateListener.LISTEN_PRECISE_CALL_STATE | 155 PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE; 156 157 private static final int MSG_USER_SWITCHED = 1; 158 159 private final Handler mHandler = new Handler() { 160 @Override 161 public void handleMessage(Message msg) { 162 switch (msg.what) { 163 case MSG_USER_SWITCHED: { 164 if (DBG) Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1); 165 TelephonyRegistry.this.notifyCellLocation(mCellLocation); 166 break; 167 } 168 } 169 } 170 }; 171 172 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 173 @Override 174 public void onReceive(Context context, Intent intent) { 175 String action = intent.getAction(); 176 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 177 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, 178 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); 179 } 180 } 181 }; 182 183 // we keep a copy of all of the state so we can send it out when folks 184 // register for it 185 // 186 // In these calls we call with the lock held. This is safe becasuse remote 187 // calls go through a oneway interface and local calls going through a 188 // handler before they get to app code. 189 190 TelephonyRegistry(Context context) { 191 CellLocation location = CellLocation.getEmpty(); 192 193 // Note that location can be null for non-phone builds like 194 // like the generic one. 195 if (location != null) { 196 location.fillInNotifierBundle(mCellLocation); 197 } 198 mContext = context; 199 mBatteryStats = BatteryStatsService.getService(); 200 mConnectedApns = new ArrayList<String>(); 201 } 202 203 public void systemRunning() { 204 // Watch for interesting updates 205 final IntentFilter filter = new IntentFilter(); 206 filter.addAction(Intent.ACTION_USER_SWITCHED); 207 filter.addAction(Intent.ACTION_USER_REMOVED); 208 mContext.registerReceiver(mBroadcastReceiver, filter); 209 } 210 211 @Override 212 public void listen(String pkgForDebug, IPhoneStateListener callback, int events, 213 boolean notifyNow) { 214 int callerUid = UserHandle.getCallingUserId(); 215 int myUid = UserHandle.myUserId(); 216 if (DBG) { 217 Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events) 218 + " myUid=" + myUid 219 + " callerUid=" + callerUid); 220 } 221 if (events != 0) { 222 /* Checks permission and throws Security exception */ 223 checkListenerPermission(events); 224 225 synchronized (mRecords) { 226 // register 227 Record r = null; 228 find_and_add: { 229 IBinder b = callback.asBinder(); 230 final int N = mRecords.size(); 231 for (int i = 0; i < N; i++) { 232 r = mRecords.get(i); 233 if (b == r.binder) { 234 break find_and_add; 235 } 236 } 237 r = new Record(); 238 r.binder = b; 239 r.callback = callback; 240 r.pkgForDebug = pkgForDebug; 241 r.callerUid = callerUid; 242 mRecords.add(r); 243 if (DBG) Slog.i(TAG, "listen: add new record=" + r); 244 } 245 int send = events & (events ^ r.events); 246 r.events = events; 247 if (notifyNow) { 248 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { 249 try { 250 r.callback.onServiceStateChanged(new ServiceState(mServiceState)); 251 } catch (RemoteException ex) { 252 remove(r.binder); 253 } 254 } 255 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { 256 try { 257 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength(); 258 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 259 : gsmSignalStrength)); 260 } catch (RemoteException ex) { 261 remove(r.binder); 262 } 263 } 264 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { 265 try { 266 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting); 267 } catch (RemoteException ex) { 268 remove(r.binder); 269 } 270 } 271 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { 272 try { 273 r.callback.onCallForwardingIndicatorChanged(mCallForwarding); 274 } catch (RemoteException ex) { 275 remove(r.binder); 276 } 277 } 278 if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) { 279 try { 280 if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + mCellLocation); 281 r.callback.onCellLocationChanged(new Bundle(mCellLocation)); 282 } catch (RemoteException ex) { 283 remove(r.binder); 284 } 285 } 286 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { 287 try { 288 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber); 289 } catch (RemoteException ex) { 290 remove(r.binder); 291 } 292 } 293 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { 294 try { 295 r.callback.onDataConnectionStateChanged(mDataConnectionState, 296 mDataConnectionNetworkType); 297 } catch (RemoteException ex) { 298 remove(r.binder); 299 } 300 } 301 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { 302 try { 303 r.callback.onDataActivity(mDataActivity); 304 } catch (RemoteException ex) { 305 remove(r.binder); 306 } 307 } 308 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { 309 try { 310 r.callback.onSignalStrengthsChanged(mSignalStrength); 311 } catch (RemoteException ex) { 312 remove(r.binder); 313 } 314 } 315 if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { 316 try { 317 r.callback.onOtaspChanged(mOtaspMode); 318 } catch (RemoteException ex) { 319 remove(r.binder); 320 } 321 } 322 if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { 323 try { 324 if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo=" + mCellInfo); 325 r.callback.onCellInfoChanged(mCellInfo); 326 } catch (RemoteException ex) { 327 remove(r.binder); 328 } 329 } 330 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) { 331 try { 332 r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo); 333 } catch (RemoteException ex) { 334 remove(r.binder); 335 } 336 } 337 if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { 338 try { 339 r.callback.onPreciseCallStateChanged(mPreciseCallState); 340 } catch (RemoteException ex) { 341 remove(r.binder); 342 } 343 } 344 if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 345 try { 346 r.callback.onPreciseDataConnectionStateChanged( 347 mPreciseDataConnectionState); 348 } catch (RemoteException ex) { 349 remove(r.binder); 350 } 351 } 352 } 353 } 354 } else { 355 remove(callback.asBinder()); 356 } 357 } 358 359 private void remove(IBinder binder) { 360 synchronized (mRecords) { 361 final int recordCount = mRecords.size(); 362 for (int i = 0; i < recordCount; i++) { 363 if (mRecords.get(i).binder == binder) { 364 mRecords.remove(i); 365 return; 366 } 367 } 368 } 369 } 370 371 public void notifyCallState(int state, String incomingNumber) { 372 if (!checkNotifyPermission("notifyCallState()")) { 373 return; 374 } 375 synchronized (mRecords) { 376 mCallState = state; 377 mCallIncomingNumber = incomingNumber; 378 for (Record r : mRecords) { 379 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { 380 try { 381 r.callback.onCallStateChanged(state, incomingNumber); 382 } catch (RemoteException ex) { 383 mRemoveList.add(r.binder); 384 } 385 } 386 } 387 handleRemoveListLocked(); 388 } 389 broadcastCallStateChanged(state, incomingNumber); 390 } 391 392 public void notifyServiceState(ServiceState state) { 393 if (!checkNotifyPermission("notifyServiceState()")){ 394 return; 395 } 396 long ident = Binder.clearCallingIdentity(); 397 try { 398 mBatteryStats.notePhoneState(state.getState()); 399 } catch (RemoteException re) { 400 // Can't do much 401 } finally { 402 Binder.restoreCallingIdentity(ident); 403 } 404 synchronized (mRecords) { 405 mServiceState = state; 406 for (Record r : mRecords) { 407 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { 408 try { 409 r.callback.onServiceStateChanged(new ServiceState(state)); 410 } catch (RemoteException ex) { 411 mRemoveList.add(r.binder); 412 } 413 } 414 } 415 handleRemoveListLocked(); 416 } 417 broadcastServiceStateChanged(state); 418 } 419 420 public void notifySignalStrength(SignalStrength signalStrength) { 421 if (!checkNotifyPermission("notifySignalStrength()")) { 422 return; 423 } 424 synchronized (mRecords) { 425 mSignalStrength = signalStrength; 426 for (Record r : mRecords) { 427 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { 428 try { 429 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength)); 430 } catch (RemoteException ex) { 431 mRemoveList.add(r.binder); 432 } 433 } 434 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { 435 try { 436 int gsmSignalStrength = signalStrength.getGsmSignalStrength(); 437 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 438 : gsmSignalStrength)); 439 } catch (RemoteException ex) { 440 mRemoveList.add(r.binder); 441 } 442 } 443 } 444 handleRemoveListLocked(); 445 } 446 broadcastSignalStrengthChanged(signalStrength); 447 } 448 449 public void notifyCellInfo(List<CellInfo> cellInfo) { 450 if (!checkNotifyPermission("notifyCellInfo()")) { 451 return; 452 } 453 454 synchronized (mRecords) { 455 mCellInfo = cellInfo; 456 for (Record r : mRecords) { 457 if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { 458 try { 459 if (DBG_LOC) { 460 Slog.d(TAG, "notifyCellInfo: mCellInfo=" + mCellInfo + " r=" + r); 461 } 462 r.callback.onCellInfoChanged(cellInfo); 463 } catch (RemoteException ex) { 464 mRemoveList.add(r.binder); 465 } 466 } 467 } 468 handleRemoveListLocked(); 469 } 470 } 471 472 public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) { 473 if (!checkNotifyPermission("notifyDataConnectionRealTimeInfo()")) { 474 return; 475 } 476 477 synchronized (mRecords) { 478 mDcRtInfo = dcRtInfo; 479 for (Record r : mRecords) { 480 if (validateEventsAndUserLocked(r, 481 PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO)) { 482 try { 483 if (DBG_LOC) { 484 Slog.d(TAG, "notifyDataConnectionRealTimeInfo: mDcRtInfo=" 485 + mDcRtInfo + " r=" + r); 486 } 487 r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo); 488 } catch (RemoteException ex) { 489 mRemoveList.add(r.binder); 490 } 491 } 492 } 493 handleRemoveListLocked(); 494 } 495 } 496 497 public void notifyMessageWaitingChanged(boolean mwi) { 498 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { 499 return; 500 } 501 synchronized (mRecords) { 502 mMessageWaiting = mwi; 503 for (Record r : mRecords) { 504 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { 505 try { 506 r.callback.onMessageWaitingIndicatorChanged(mwi); 507 } catch (RemoteException ex) { 508 mRemoveList.add(r.binder); 509 } 510 } 511 } 512 handleRemoveListLocked(); 513 } 514 } 515 516 public void notifyCallForwardingChanged(boolean cfi) { 517 if (!checkNotifyPermission("notifyCallForwardingChanged()")) { 518 return; 519 } 520 synchronized (mRecords) { 521 mCallForwarding = cfi; 522 for (Record r : mRecords) { 523 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { 524 try { 525 r.callback.onCallForwardingIndicatorChanged(cfi); 526 } catch (RemoteException ex) { 527 mRemoveList.add(r.binder); 528 } 529 } 530 } 531 handleRemoveListLocked(); 532 } 533 } 534 535 public void notifyDataActivity(int state) { 536 if (!checkNotifyPermission("notifyDataActivity()" )) { 537 return; 538 } 539 synchronized (mRecords) { 540 mDataActivity = state; 541 for (Record r : mRecords) { 542 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { 543 try { 544 r.callback.onDataActivity(state); 545 } catch (RemoteException ex) { 546 mRemoveList.add(r.binder); 547 } 548 } 549 } 550 handleRemoveListLocked(); 551 } 552 } 553 554 public void notifyDataConnection(int state, boolean isDataConnectivityPossible, 555 String reason, String apn, String apnType, LinkProperties linkProperties, 556 NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { 557 if (!checkNotifyPermission("notifyDataConnection()" )) { 558 return; 559 } 560 if (DBG) { 561 Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" 562 + isDataConnectivityPossible + " reason='" + reason 563 + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType 564 + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords); 565 } 566 synchronized (mRecords) { 567 boolean modified = false; 568 if (state == TelephonyManager.DATA_CONNECTED) { 569 if (!mConnectedApns.contains(apnType)) { 570 mConnectedApns.add(apnType); 571 if (mDataConnectionState != state) { 572 mDataConnectionState = state; 573 modified = true; 574 } 575 } 576 } else { 577 if (mConnectedApns.remove(apnType)) { 578 if (mConnectedApns.isEmpty()) { 579 mDataConnectionState = state; 580 modified = true; 581 } else { 582 // leave mDataConnectionState as is and 583 // send out the new status for the APN in question. 584 } 585 } 586 } 587 mDataConnectionPossible = isDataConnectivityPossible; 588 mDataConnectionReason = reason; 589 mDataConnectionLinkProperties = linkProperties; 590 mDataConnectionNetworkCapabilities = networkCapabilities; 591 if (mDataConnectionNetworkType != networkType) { 592 mDataConnectionNetworkType = networkType; 593 // need to tell registered listeners about the new network type 594 modified = true; 595 } 596 if (modified) { 597 if (DBG) { 598 Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState 599 + ", " + mDataConnectionNetworkType + ")"); 600 } 601 for (Record r : mRecords) { 602 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { 603 try { 604 r.callback.onDataConnectionStateChanged(mDataConnectionState, 605 mDataConnectionNetworkType); 606 } catch (RemoteException ex) { 607 mRemoveList.add(r.binder); 608 } 609 } 610 } 611 handleRemoveListLocked(); 612 } 613 mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType, 614 apnType, apn, reason, linkProperties, ""); 615 for (Record r : mRecords) { 616 if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 617 try { 618 r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); 619 } catch (RemoteException ex) { 620 mRemoveList.add(r.binder); 621 } 622 } 623 } 624 handleRemoveListLocked(); 625 } 626 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, 627 apnType, linkProperties, networkCapabilities, roaming); 628 broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason, 629 linkProperties, ""); 630 } 631 632 public void notifyDataConnectionFailed(String reason, String apnType) { 633 if (!checkNotifyPermission("notifyDataConnectionFailed()")) { 634 return; 635 } 636 synchronized (mRecords) { 637 mPreciseDataConnectionState = new PreciseDataConnectionState( 638 TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN, 639 apnType, "", reason, null, ""); 640 for (Record r : mRecords) { 641 if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 642 try { 643 r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); 644 } catch (RemoteException ex) { 645 mRemoveList.add(r.binder); 646 } 647 } 648 } 649 handleRemoveListLocked(); 650 } 651 broadcastDataConnectionFailed(reason, apnType); 652 broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN, 653 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, ""); 654 } 655 656 public void notifyCellLocation(Bundle cellLocation) { 657 if (!checkNotifyPermission("notifyCellLocation()")) { 658 return; 659 } 660 synchronized (mRecords) { 661 mCellLocation = cellLocation; 662 for (Record r : mRecords) { 663 if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) { 664 try { 665 if (DBG_LOC) { 666 Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation 667 + " r=" + r); 668 } 669 r.callback.onCellLocationChanged(new Bundle(cellLocation)); 670 } catch (RemoteException ex) { 671 mRemoveList.add(r.binder); 672 } 673 674 } 675 } 676 handleRemoveListLocked(); 677 } 678 } 679 680 public void notifyOtaspChanged(int otaspMode) { 681 if (!checkNotifyPermission("notifyOtaspChanged()" )) { 682 return; 683 } 684 synchronized (mRecords) { 685 mOtaspMode = otaspMode; 686 for (Record r : mRecords) { 687 if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { 688 try { 689 r.callback.onOtaspChanged(otaspMode); 690 } catch (RemoteException ex) { 691 mRemoveList.add(r.binder); 692 } 693 } 694 } 695 handleRemoveListLocked(); 696 } 697 } 698 699 public void notifyPreciseCallState(int ringingCallState, int foregroundCallState, 700 int backgroundCallState) { 701 if (!checkNotifyPermission("notifyPreciseCallState()")) { 702 return; 703 } 704 synchronized (mRecords) { 705 mRingingCallState = ringingCallState; 706 mForegroundCallState = foregroundCallState; 707 mBackgroundCallState = backgroundCallState; 708 mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState, 709 backgroundCallState, 710 DisconnectCause.NOT_VALID, 711 PreciseDisconnectCause.NOT_VALID); 712 for (Record r : mRecords) { 713 if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { 714 try { 715 r.callback.onPreciseCallStateChanged(mPreciseCallState); 716 } catch (RemoteException ex) { 717 mRemoveList.add(r.binder); 718 } 719 } 720 } 721 handleRemoveListLocked(); 722 } 723 broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, 724 DisconnectCause.NOT_VALID, 725 PreciseDisconnectCause.NOT_VALID); 726 } 727 728 public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) { 729 if (!checkNotifyPermission("notifyDisconnectCause()")) { 730 return; 731 } 732 synchronized (mRecords) { 733 mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState, 734 mBackgroundCallState, disconnectCause, preciseDisconnectCause); 735 for (Record r : mRecords) { 736 if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { 737 try { 738 r.callback.onPreciseCallStateChanged(mPreciseCallState); 739 } catch (RemoteException ex) { 740 mRemoveList.add(r.binder); 741 } 742 } 743 } 744 handleRemoveListLocked(); 745 } 746 broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState, 747 mBackgroundCallState, disconnectCause, preciseDisconnectCause); 748 } 749 750 public void notifyPreciseDataConnectionFailed(String reason, String apnType, 751 String apn, String failCause) { 752 if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { 753 return; 754 } 755 synchronized (mRecords) { 756 mPreciseDataConnectionState = new PreciseDataConnectionState( 757 TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN, 758 apnType, apn, reason, null, failCause); 759 for (Record r : mRecords) { 760 if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 761 try { 762 r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); 763 } catch (RemoteException ex) { 764 mRemoveList.add(r.binder); 765 } 766 } 767 } 768 handleRemoveListLocked(); 769 } 770 broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN, 771 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause); 772 } 773 774 @Override 775 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 776 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 777 != PackageManager.PERMISSION_GRANTED) { 778 pw.println("Permission Denial: can't dump telephony.registry from from pid=" 779 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 780 return; 781 } 782 synchronized (mRecords) { 783 final int recordCount = mRecords.size(); 784 pw.println("last known state:"); 785 pw.println(" mCallState=" + mCallState); 786 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber); 787 pw.println(" mServiceState=" + mServiceState); 788 pw.println(" mSignalStrength=" + mSignalStrength); 789 pw.println(" mMessageWaiting=" + mMessageWaiting); 790 pw.println(" mCallForwarding=" + mCallForwarding); 791 pw.println(" mDataActivity=" + mDataActivity); 792 pw.println(" mDataConnectionState=" + mDataConnectionState); 793 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible); 794 pw.println(" mDataConnectionReason=" + mDataConnectionReason); 795 pw.println(" mDataConnectionApn=" + mDataConnectionApn); 796 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties); 797 pw.println(" mDataConnectionNetworkCapabilities=" + 798 mDataConnectionNetworkCapabilities); 799 pw.println(" mCellLocation=" + mCellLocation); 800 pw.println(" mCellInfo=" + mCellInfo); 801 pw.println(" mDcRtInfo=" + mDcRtInfo); 802 pw.println("registrations: count=" + recordCount); 803 for (Record r : mRecords) { 804 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); 805 } 806 } 807 } 808 809 // 810 // the legacy intent broadcasting 811 // 812 813 private void broadcastServiceStateChanged(ServiceState state) { 814 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 815 Bundle data = new Bundle(); 816 state.fillInNotifierBundle(data); 817 intent.putExtras(data); 818 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 819 } 820 821 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) { 822 long ident = Binder.clearCallingIdentity(); 823 try { 824 mBatteryStats.notePhoneSignalStrength(signalStrength); 825 } catch (RemoteException e) { 826 /* The remote entity disappeared, we can safely ignore the exception. */ 827 } finally { 828 Binder.restoreCallingIdentity(ident); 829 } 830 831 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); 832 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 833 Bundle data = new Bundle(); 834 signalStrength.fillInNotifierBundle(data); 835 intent.putExtras(data); 836 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 837 } 838 839 private void broadcastCallStateChanged(int state, String incomingNumber) { 840 long ident = Binder.clearCallingIdentity(); 841 try { 842 if (state == TelephonyManager.CALL_STATE_IDLE) { 843 mBatteryStats.notePhoneOff(); 844 } else { 845 mBatteryStats.notePhoneOn(); 846 } 847 } catch (RemoteException e) { 848 /* The remote entity disappeared, we can safely ignore the exception. */ 849 } finally { 850 Binder.restoreCallingIdentity(ident); 851 } 852 853 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED); 854 intent.putExtra(PhoneConstants.STATE_KEY, 855 DefaultPhoneNotifier.convertCallState(state).toString()); 856 if (!TextUtils.isEmpty(incomingNumber)) { 857 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); 858 } 859 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 860 android.Manifest.permission.READ_PHONE_STATE); 861 } 862 863 private void broadcastDataConnectionStateChanged(int state, 864 boolean isDataConnectivityPossible, 865 String reason, String apn, String apnType, LinkProperties linkProperties, 866 NetworkCapabilities networkCapabilities, boolean roaming) { 867 // Note: not reporting to the battery stats service here, because the 868 // status bar takes care of that after taking into account all of the 869 // required info. 870 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); 871 intent.putExtra(PhoneConstants.STATE_KEY, 872 DefaultPhoneNotifier.convertDataState(state).toString()); 873 if (!isDataConnectivityPossible) { 874 intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true); 875 } 876 if (reason != null) { 877 intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason); 878 } 879 if (linkProperties != null) { 880 intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties); 881 String iface = linkProperties.getInterfaceName(); 882 if (iface != null) { 883 intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface); 884 } 885 } 886 if (networkCapabilities != null) { 887 intent.putExtra(PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY, networkCapabilities); 888 } 889 if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true); 890 891 intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); 892 intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); 893 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 894 } 895 896 private void broadcastDataConnectionFailed(String reason, String apnType) { 897 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); 898 intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason); 899 intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); 900 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 901 } 902 903 private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState, 904 int backgroundCallState, int disconnectCause, int preciseDisconnectCause) { 905 Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED); 906 intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState); 907 intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState); 908 intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState); 909 intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause); 910 intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause); 911 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 912 android.Manifest.permission.READ_PRECISE_PHONE_STATE); 913 } 914 915 private void broadcastPreciseDataConnectionStateChanged(int state, int networkType, 916 String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) { 917 Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED); 918 intent.putExtra(PhoneConstants.STATE_KEY, state); 919 intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType); 920 if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason); 921 if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); 922 if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); 923 if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties); 924 if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause); 925 926 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 927 android.Manifest.permission.READ_PRECISE_PHONE_STATE); 928 } 929 930 private boolean checkNotifyPermission(String method) { 931 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 932 == PackageManager.PERMISSION_GRANTED) { 933 return true; 934 } 935 String msg = "Modify Phone State Permission Denial: " + method + " from pid=" 936 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid(); 937 if (DBG) Slog.w(TAG, msg); 938 return false; 939 } 940 941 private void checkListenerPermission(int events) { 942 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { 943 mContext.enforceCallingOrSelfPermission( 944 android.Manifest.permission.ACCESS_COARSE_LOCATION, null); 945 946 } 947 948 if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { 949 mContext.enforceCallingOrSelfPermission( 950 android.Manifest.permission.ACCESS_COARSE_LOCATION, null); 951 952 } 953 954 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) { 955 mContext.enforceCallingOrSelfPermission( 956 android.Manifest.permission.READ_PHONE_STATE, null); 957 } 958 959 if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) { 960 mContext.enforceCallingOrSelfPermission( 961 android.Manifest.permission.READ_PRECISE_PHONE_STATE, null); 962 963 } 964 } 965 966 private void handleRemoveListLocked() { 967 if (mRemoveList.size() > 0) { 968 for (IBinder b: mRemoveList) { 969 remove(b); 970 } 971 mRemoveList.clear(); 972 } 973 } 974 975 private boolean validateEventsAndUserLocked(Record r, int events) { 976 int foregroundUser; 977 long callingIdentity = Binder.clearCallingIdentity(); 978 boolean valid = false; 979 try { 980 foregroundUser = ActivityManager.getCurrentUser(); 981 valid = r.callerUid == foregroundUser && (r.events & events) != 0; 982 if (DBG | DBG_LOC) { 983 Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid 984 + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser 985 + " r.events=" + r.events + " events=" + events); 986 } 987 } finally { 988 Binder.restoreCallingIdentity(callingIdentity); 989 } 990 return valid; 991 } 992} 993