OSDN Git Service

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