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