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