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