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.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