TelephonyRegistry.java revision 070e061a289d771e62b58379eaed153fd285b04f
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.LinkCapabilities; 26import android.net.LinkProperties; 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 LinkCapabilities mDataConnectionLinkCapabilities; 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 synchronized (mRecords) { 397 mServiceState = state; 398 for (Record r : mRecords) { 399 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { 400 try { 401 r.callback.onServiceStateChanged(new ServiceState(state)); 402 } catch (RemoteException ex) { 403 mRemoveList.add(r.binder); 404 } 405 } 406 } 407 handleRemoveListLocked(); 408 } 409 broadcastServiceStateChanged(state); 410 } 411 412 public void notifySignalStrength(SignalStrength signalStrength) { 413 if (!checkNotifyPermission("notifySignalStrength()")) { 414 return; 415 } 416 synchronized (mRecords) { 417 mSignalStrength = signalStrength; 418 for (Record r : mRecords) { 419 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { 420 try { 421 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength)); 422 } catch (RemoteException ex) { 423 mRemoveList.add(r.binder); 424 } 425 } 426 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { 427 try { 428 int gsmSignalStrength = signalStrength.getGsmSignalStrength(); 429 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 430 : gsmSignalStrength)); 431 } catch (RemoteException ex) { 432 mRemoveList.add(r.binder); 433 } 434 } 435 } 436 handleRemoveListLocked(); 437 } 438 broadcastSignalStrengthChanged(signalStrength); 439 } 440 441 public void notifyCellInfo(List<CellInfo> cellInfo) { 442 if (!checkNotifyPermission("notifyCellInfo()")) { 443 return; 444 } 445 446 synchronized (mRecords) { 447 mCellInfo = cellInfo; 448 for (Record r : mRecords) { 449 if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { 450 try { 451 if (DBG_LOC) { 452 Slog.d(TAG, "notifyCellInfo: mCellInfo=" + mCellInfo + " r=" + r); 453 } 454 r.callback.onCellInfoChanged(cellInfo); 455 } catch (RemoteException ex) { 456 mRemoveList.add(r.binder); 457 } 458 } 459 } 460 handleRemoveListLocked(); 461 } 462 } 463 464 public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) { 465 if (!checkNotifyPermission("notifyDataConnectionRealTimeInfo()")) { 466 return; 467 } 468 469 synchronized (mRecords) { 470 mDcRtInfo = dcRtInfo; 471 for (Record r : mRecords) { 472 if (validateEventsAndUserLocked(r, 473 PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO)) { 474 try { 475 if (DBG_LOC) { 476 Slog.d(TAG, "notifyDataConnectionRealTimeInfo: mDcRtInfo=" 477 + mDcRtInfo + " r=" + r); 478 } 479 r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo); 480 } catch (RemoteException ex) { 481 mRemoveList.add(r.binder); 482 } 483 } 484 } 485 handleRemoveListLocked(); 486 } 487 } 488 489 public void notifyMessageWaitingChanged(boolean mwi) { 490 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { 491 return; 492 } 493 synchronized (mRecords) { 494 mMessageWaiting = mwi; 495 for (Record r : mRecords) { 496 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { 497 try { 498 r.callback.onMessageWaitingIndicatorChanged(mwi); 499 } catch (RemoteException ex) { 500 mRemoveList.add(r.binder); 501 } 502 } 503 } 504 handleRemoveListLocked(); 505 } 506 } 507 508 public void notifyCallForwardingChanged(boolean cfi) { 509 if (!checkNotifyPermission("notifyCallForwardingChanged()")) { 510 return; 511 } 512 synchronized (mRecords) { 513 mCallForwarding = cfi; 514 for (Record r : mRecords) { 515 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { 516 try { 517 r.callback.onCallForwardingIndicatorChanged(cfi); 518 } catch (RemoteException ex) { 519 mRemoveList.add(r.binder); 520 } 521 } 522 } 523 handleRemoveListLocked(); 524 } 525 } 526 527 public void notifyDataActivity(int state) { 528 if (!checkNotifyPermission("notifyDataActivity()" )) { 529 return; 530 } 531 synchronized (mRecords) { 532 mDataActivity = state; 533 for (Record r : mRecords) { 534 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { 535 try { 536 r.callback.onDataActivity(state); 537 } catch (RemoteException ex) { 538 mRemoveList.add(r.binder); 539 } 540 } 541 } 542 handleRemoveListLocked(); 543 } 544 } 545 546 public void notifyDataConnection(int state, boolean isDataConnectivityPossible, 547 String reason, String apn, String apnType, LinkProperties linkProperties, 548 LinkCapabilities linkCapabilities, int networkType, boolean roaming) { 549 if (!checkNotifyPermission("notifyDataConnection()" )) { 550 return; 551 } 552 if (DBG) { 553 Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" 554 + isDataConnectivityPossible + " reason='" + reason 555 + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType 556 + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords); 557 } 558 synchronized (mRecords) { 559 boolean modified = false; 560 if (state == TelephonyManager.DATA_CONNECTED) { 561 if (!mConnectedApns.contains(apnType)) { 562 mConnectedApns.add(apnType); 563 if (mDataConnectionState != state) { 564 mDataConnectionState = state; 565 modified = true; 566 } 567 } 568 } else { 569 if (mConnectedApns.remove(apnType)) { 570 if (mConnectedApns.isEmpty()) { 571 mDataConnectionState = state; 572 modified = true; 573 } else { 574 // leave mDataConnectionState as is and 575 // send out the new status for the APN in question. 576 } 577 } 578 } 579 mDataConnectionPossible = isDataConnectivityPossible; 580 mDataConnectionReason = reason; 581 mDataConnectionLinkProperties = linkProperties; 582 mDataConnectionLinkCapabilities = linkCapabilities; 583 if (mDataConnectionNetworkType != networkType) { 584 mDataConnectionNetworkType = networkType; 585 // need to tell registered listeners about the new network type 586 modified = true; 587 } 588 if (modified) { 589 if (DBG) { 590 Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState 591 + ", " + mDataConnectionNetworkType + ")"); 592 } 593 for (Record r : mRecords) { 594 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { 595 try { 596 r.callback.onDataConnectionStateChanged(mDataConnectionState, 597 mDataConnectionNetworkType); 598 } catch (RemoteException ex) { 599 mRemoveList.add(r.binder); 600 } 601 } 602 } 603 handleRemoveListLocked(); 604 } 605 mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType, 606 apnType, apn, reason, linkProperties, ""); 607 for (Record r : mRecords) { 608 if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 609 try { 610 r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); 611 } catch (RemoteException ex) { 612 mRemoveList.add(r.binder); 613 } 614 } 615 } 616 handleRemoveListLocked(); 617 } 618 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, 619 apnType, linkProperties, linkCapabilities, roaming); 620 broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason, 621 linkProperties, ""); 622 } 623 624 public void notifyDataConnectionFailed(String reason, String apnType) { 625 if (!checkNotifyPermission("notifyDataConnectionFailed()")) { 626 return; 627 } 628 synchronized (mRecords) { 629 mPreciseDataConnectionState = new PreciseDataConnectionState( 630 TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN, 631 apnType, "", reason, null, ""); 632 for (Record r : mRecords) { 633 if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 634 try { 635 r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); 636 } catch (RemoteException ex) { 637 mRemoveList.add(r.binder); 638 } 639 } 640 } 641 handleRemoveListLocked(); 642 } 643 broadcastDataConnectionFailed(reason, apnType); 644 broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN, 645 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, ""); 646 } 647 648 public void notifyCellLocation(Bundle cellLocation) { 649 if (!checkNotifyPermission("notifyCellLocation()")) { 650 return; 651 } 652 synchronized (mRecords) { 653 mCellLocation = cellLocation; 654 for (Record r : mRecords) { 655 if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) { 656 try { 657 if (DBG_LOC) { 658 Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation 659 + " r=" + r); 660 } 661 r.callback.onCellLocationChanged(new Bundle(cellLocation)); 662 } catch (RemoteException ex) { 663 mRemoveList.add(r.binder); 664 } 665 666 } 667 } 668 handleRemoveListLocked(); 669 } 670 } 671 672 public void notifyOtaspChanged(int otaspMode) { 673 if (!checkNotifyPermission("notifyOtaspChanged()" )) { 674 return; 675 } 676 synchronized (mRecords) { 677 mOtaspMode = otaspMode; 678 for (Record r : mRecords) { 679 if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { 680 try { 681 r.callback.onOtaspChanged(otaspMode); 682 } catch (RemoteException ex) { 683 mRemoveList.add(r.binder); 684 } 685 } 686 } 687 handleRemoveListLocked(); 688 } 689 } 690 691 public void notifyPreciseCallState(int ringingCallState, int foregroundCallState, 692 int backgroundCallState) { 693 if (!checkNotifyPermission("notifyPreciseCallState()")) { 694 return; 695 } 696 synchronized (mRecords) { 697 mRingingCallState = ringingCallState; 698 mForegroundCallState = foregroundCallState; 699 mBackgroundCallState = backgroundCallState; 700 mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState, 701 backgroundCallState, 702 DisconnectCause.NOT_VALID, 703 PreciseDisconnectCause.NOT_VALID); 704 for (Record r : mRecords) { 705 if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { 706 try { 707 r.callback.onPreciseCallStateChanged(mPreciseCallState); 708 } catch (RemoteException ex) { 709 mRemoveList.add(r.binder); 710 } 711 } 712 } 713 handleRemoveListLocked(); 714 } 715 broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, 716 DisconnectCause.NOT_VALID, 717 PreciseDisconnectCause.NOT_VALID); 718 } 719 720 public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) { 721 if (!checkNotifyPermission("notifyDisconnectCause()")) { 722 return; 723 } 724 synchronized (mRecords) { 725 mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState, 726 mBackgroundCallState, disconnectCause, preciseDisconnectCause); 727 for (Record r : mRecords) { 728 if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) { 729 try { 730 r.callback.onPreciseCallStateChanged(mPreciseCallState); 731 } catch (RemoteException ex) { 732 mRemoveList.add(r.binder); 733 } 734 } 735 } 736 handleRemoveListLocked(); 737 } 738 broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState, 739 mBackgroundCallState, disconnectCause, preciseDisconnectCause); 740 } 741 742 public void notifyPreciseDataConnectionFailed(String reason, String apnType, 743 String apn, String failCause) { 744 if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { 745 return; 746 } 747 synchronized (mRecords) { 748 mPreciseDataConnectionState = new PreciseDataConnectionState( 749 TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN, 750 apnType, apn, reason, null, failCause); 751 for (Record r : mRecords) { 752 if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { 753 try { 754 r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState); 755 } catch (RemoteException ex) { 756 mRemoveList.add(r.binder); 757 } 758 } 759 } 760 handleRemoveListLocked(); 761 } 762 broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN, 763 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause); 764 } 765 766 @Override 767 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 768 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 769 != PackageManager.PERMISSION_GRANTED) { 770 pw.println("Permission Denial: can't dump telephony.registry from from pid=" 771 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 772 return; 773 } 774 synchronized (mRecords) { 775 final int recordCount = mRecords.size(); 776 pw.println("last known state:"); 777 pw.println(" mCallState=" + mCallState); 778 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber); 779 pw.println(" mServiceState=" + mServiceState); 780 pw.println(" mSignalStrength=" + mSignalStrength); 781 pw.println(" mMessageWaiting=" + mMessageWaiting); 782 pw.println(" mCallForwarding=" + mCallForwarding); 783 pw.println(" mDataActivity=" + mDataActivity); 784 pw.println(" mDataConnectionState=" + mDataConnectionState); 785 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible); 786 pw.println(" mDataConnectionReason=" + mDataConnectionReason); 787 pw.println(" mDataConnectionApn=" + mDataConnectionApn); 788 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties); 789 pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities); 790 pw.println(" mCellLocation=" + mCellLocation); 791 pw.println(" mCellInfo=" + mCellInfo); 792 pw.println(" mDcRtInfo=" + mDcRtInfo); 793 pw.println("registrations: count=" + recordCount); 794 for (Record r : mRecords) { 795 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); 796 } 797 } 798 } 799 800 // 801 // the legacy intent broadcasting 802 // 803 804 private void broadcastServiceStateChanged(ServiceState state) { 805 long ident = Binder.clearCallingIdentity(); 806 try { 807 mBatteryStats.notePhoneState(state.getState()); 808 } catch (RemoteException re) { 809 // Can't do much 810 } finally { 811 Binder.restoreCallingIdentity(ident); 812 } 813 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 LinkCapabilities linkCapabilities, 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 (linkCapabilities != null) { 887 intent.putExtra(PhoneConstants.DATA_LINK_CAPABILITIES_KEY, linkCapabilities); 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