TelephonyRegistry.java revision eeacf9374748a5f7fc96a1beaf18c353d473d752
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.app.ActivityManager;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.pm.PackageManager;
25import android.net.LinkProperties;
26import android.net.NetworkCapabilities;
27import android.os.Binder;
28import android.os.Bundle;
29import android.os.Handler;
30import android.os.IBinder;
31import android.os.Message;
32import android.os.RemoteException;
33import android.os.UserHandle;
34import android.telephony.CellLocation;
35import android.telephony.DataConnectionRealTimeInfo;
36import android.telephony.TelephonyManager;
37import android.telephony.SubscriptionManager;
38import android.telephony.PhoneStateListener;
39import android.telephony.ServiceState;
40import android.telephony.SignalStrength;
41import android.telephony.CellInfo;
42import android.telephony.VoLteServiceState;
43import android.telephony.TelephonyManager;
44import android.telephony.DisconnectCause;
45import android.telephony.PreciseCallState;
46import android.telephony.PreciseDataConnectionState;
47import android.telephony.PreciseDisconnectCause;
48import android.text.TextUtils;
49import android.util.Slog;
50
51import java.util.ArrayList;
52import java.util.List;
53import java.io.FileDescriptor;
54import java.io.PrintWriter;
55
56import com.android.internal.app.IBatteryStats;
57import com.android.internal.telephony.ITelephonyRegistry;
58import com.android.internal.telephony.IPhoneStateListener;
59import com.android.internal.telephony.DefaultPhoneNotifier;
60import com.android.internal.telephony.PhoneConstants;
61import com.android.internal.telephony.ServiceStateTracker;
62import com.android.internal.telephony.TelephonyIntents;
63import com.android.server.am.BatteryStatsService;
64
65/**
66 * Since phone process can be restarted, this class provides a centralized place
67 * that applications can register and be called back from.
68 */
69class TelephonyRegistry extends ITelephonyRegistry.Stub {
70    private static final String TAG = "TelephonyRegistry";
71    private static final boolean DBG = false; // STOPSHIP if true
72    private static final boolean DBG_LOC = false; // STOPSHIP if true
73    private static final boolean VDBG = false; // STOPSHIP if true
74
75    private static class Record {
76        String pkgForDebug;
77
78        IBinder binder;
79
80        IPhoneStateListener callback;
81
82        int callerUid;
83
84        int events;
85
86        long subId;
87
88        boolean isLegacyApp;
89
90        @Override
91        public String toString() {
92            return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid + " subId=" + subId +
93                    " events=" + Integer.toHexString(events) + "}";
94        }
95    }
96
97    private final Context mContext;
98
99    // access should be inside synchronized (mRecords) for these two fields
100    private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
101    private final ArrayList<Record> mRecords = new ArrayList<Record>();
102
103    private final IBatteryStats mBatteryStats;
104
105    private int mNumPhones;
106
107    private int[] mCallState;
108
109    private String[] mCallIncomingNumber;
110
111    private ServiceState[] mServiceState;
112
113    private SignalStrength[] mSignalStrength;
114
115    private boolean[] mMessageWaiting;
116
117    private boolean[] mCallForwarding;
118
119    private int[] mDataActivity;
120
121    private int[] mDataConnectionState;
122
123    private boolean[] mDataConnectionPossible;
124
125    private String[] mDataConnectionReason;
126
127    private String[] mDataConnectionApn;
128
129    private ArrayList<String> mConnectedApns;
130
131    private LinkProperties[] mDataConnectionLinkProperties;
132
133    private NetworkCapabilities[] mDataConnectionNetworkCapabilities;
134
135    private Bundle[] mCellLocation;
136
137    private int[] mDataConnectionNetworkType;
138
139    private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
140
141    private ArrayList<List<CellInfo>> mCellInfo = null;
142
143    private VoLteServiceState mVoLteServiceState = new VoLteServiceState();
144
145    private long mDefaultSubId;
146
147    private DataConnectionRealTimeInfo mDcRtInfo = new DataConnectionRealTimeInfo();
148
149    private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
150
151    private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
152
153    private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
154
155    private PreciseCallState mPreciseCallState = new PreciseCallState();
156
157    private PreciseDataConnectionState mPreciseDataConnectionState =
158                new PreciseDataConnectionState();
159
160    static final int PHONE_STATE_PERMISSION_MASK =
161                PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
162                PhoneStateListener.LISTEN_CALL_STATE |
163                PhoneStateListener.LISTEN_DATA_ACTIVITY |
164                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
165                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
166                PhoneStateListener.LISTEN_VOLTE_STATE;;
167
168    static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
169                PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
170                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
171
172    private static final int MSG_USER_SWITCHED = 1;
173    private static final int MSG_UPDATE_DEFAULT_SUB = 2;
174
175    private final Handler mHandler = new Handler() {
176        @Override
177        public void handleMessage(Message msg) {
178            switch (msg.what) {
179                case MSG_USER_SWITCHED: {
180                    Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
181                    int numPhones = TelephonyManager.getDefault().getPhoneCount();
182                    for (int sub = 0; sub < numPhones; sub++) {
183                        TelephonyRegistry.this.notifyCellLocationUsingSubId(sub, mCellLocation[sub]);
184                    }
185                    break;
186                }
187                case MSG_UPDATE_DEFAULT_SUB: {
188                    Slog.d(TAG, "MSG_UPDATE_DEFAULT_SUB subid=" + mDefaultSubId);
189                    // Default subscription id changed, update the changed default subscription
190                    // id in  all the legacy application listener records.
191                    synchronized (mRecords) {
192                        for (Record r : mRecords) {
193                            // FIXME: Be sure we're using isLegacyApp correctly!
194                            if (r.isLegacyApp == true) {
195                                r.subId = mDefaultSubId;
196                            }
197                        }
198                    }
199                    break;
200                }
201            }
202        }
203    };
204
205    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
206        @Override
207        public void onReceive(Context context, Intent intent) {
208            String action = intent.getAction();
209            Slog.d(TAG, "mBroadcastReceiver: action=" + action);
210            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
211                int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
212                if (DBG) Slog.d(TAG, "onReceive: userHandle=" + userHandle);
213                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, userHandle, 0));
214            } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED)) {
215                mDefaultSubId = intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY,
216                        SubscriptionManager.getDefaultSubId());
217                if (DBG) Slog.d(TAG, "onReceive: mDefaultSubId=" + mDefaultSubId);
218                mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_DEFAULT_SUB, 0, 0));
219            }
220        }
221    };
222
223    // we keep a copy of all of the state so we can send it out when folks
224    // register for it
225    //
226    // In these calls we call with the lock held. This is safe becasuse remote
227    // calls go through a oneway interface and local calls going through a
228    // handler before they get to app code.
229
230    TelephonyRegistry(Context context) {
231        CellLocation  location = CellLocation.getEmpty();
232
233        mContext = context;
234        mBatteryStats = BatteryStatsService.getService();
235        mConnectedApns = new ArrayList<String>();
236
237        // Initialize default subscription to be used for single standby.
238        mDefaultSubId = SubscriptionManager.getDefaultSubId();
239
240        int numPhones = TelephonyManager.getDefault().getPhoneCount();
241        if (DBG) Slog.d(TAG, "TelephonyRegistor: ctor numPhones=" + numPhones);
242        mNumPhones = numPhones;
243        mCallState = new int[numPhones];
244        mDataActivity = new int[numPhones];
245        mDataConnectionState = new int[numPhones];
246        mDataConnectionNetworkType = new int[numPhones];
247        mCallIncomingNumber = new String[numPhones];
248        mServiceState = new ServiceState[numPhones];
249        mSignalStrength = new SignalStrength[numPhones];
250        mMessageWaiting = new boolean[numPhones];
251        mDataConnectionPossible = new boolean[numPhones];
252        mDataConnectionReason = new String[numPhones];
253        mDataConnectionApn = new String[numPhones];
254        mCallForwarding = new boolean[numPhones];
255        mCellLocation = new Bundle[numPhones];
256        mDataConnectionLinkProperties = new LinkProperties[numPhones];
257        mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
258        mCellInfo = new ArrayList<List<CellInfo>>();
259        for (int i = 0; i < numPhones; i++) {
260            mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
261            mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
262            mDataConnectionState[i] = TelephonyManager.DATA_UNKNOWN;
263            mCallIncomingNumber[i] =  "";
264            mServiceState[i] =  new ServiceState();
265            mSignalStrength[i] =  new SignalStrength();
266            mMessageWaiting[i] =  false;
267            mCallForwarding[i] =  false;
268            mDataConnectionPossible[i] = false;
269            mDataConnectionReason[i] =  "";
270            mDataConnectionApn[i] =  "";
271            mCellLocation[i] = new Bundle();
272            mCellInfo.add(i, null);
273        }
274
275        // Note that location can be null for non-phone builds like
276        // like the generic one.
277        if (location != null) {
278            for (int i = 0; i < numPhones; i++) {
279                location.fillInNotifierBundle(mCellLocation[i]);
280            }
281        }
282        mConnectedApns = new ArrayList<String>();
283    }
284
285    public void systemRunning() {
286        // Watch for interesting updates
287        final IntentFilter filter = new IntentFilter();
288        filter.addAction(Intent.ACTION_USER_SWITCHED);
289        filter.addAction(Intent.ACTION_USER_REMOVED);
290        filter.addAction(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
291        Slog.d(TAG, "systemRunning register for intents");
292        mContext.registerReceiver(mBroadcastReceiver, filter);
293    }
294
295    @Override
296    public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
297            boolean notifyNow) {
298        listen(pkgForDebug, callback, events, notifyNow, mDefaultSubId, true);
299    }
300
301    @Override
302    public void listenUsingSubId(long subId, String pkgForDebug, IPhoneStateListener callback,
303            int events, boolean notifyNow) {
304        listen(pkgForDebug, callback, events, notifyNow, subId, false);
305    }
306
307    private void listen(String pkgForDebug, IPhoneStateListener callback, int events,
308            boolean notifyNow, long subId, boolean isLegacyApp) {
309        int callerUid = UserHandle.getCallingUserId();
310        int myUid = UserHandle.myUserId();
311        if (VDBG) {
312            Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
313                + " notifyNow=" + notifyNow + " subId=" + subId
314                + " isLegacyApp=" + isLegacyApp
315                + " myUid=" + myUid
316                + " callerUid=" + callerUid);
317        }
318        if (events != 0) {
319            /* Checks permission and throws Security exception */
320            checkListenerPermission(events);
321
322            synchronized (mRecords) {
323                // register
324                Record r = null;
325                find_and_add: {
326                    IBinder b = callback.asBinder();
327                    final int N = mRecords.size();
328                    for (int i = 0; i < N; i++) {
329                        r = mRecords.get(i);
330                        if (b == r.binder) {
331                            break find_and_add;
332                        }
333                    }
334                    r = new Record();
335                    r.binder = b;
336                    r.callback = callback;
337                    r.pkgForDebug = pkgForDebug;
338                    r.callerUid = callerUid;
339                    r.subId = subId;
340                    r.isLegacyApp = isLegacyApp;
341                    // Legacy applications pass invalid subId(-1), based on
342                    // the received subId value update the isLegacyApp field
343                    if ((r.subId <= 0) || (r.subId == SubscriptionManager.INVALID_SUB_ID)) {
344                        r.subId = mDefaultSubId;
345                        r.isLegacyApp = true; // r.subId is to be update when default changes.
346                    }
347                    if (r.subId == SubscriptionManager.DEFAULT_SUB_ID) {
348                        r.subId = mDefaultSubId;
349                        r.isLegacyApp = true; // r.subId is to be update when default changes.
350                        if (DBG) Slog.i(TAG, "listen: DEFAULT_SUB_ID");
351                    }
352                    mRecords.add(r);
353                    if (DBG) Slog.i(TAG, "listen: add new record");
354                }
355                int phoneId = SubscriptionManager.getPhoneId(subId);
356                r.events = events;
357                if (DBG) Slog.i(TAG, "listen: set events record=" + r);
358                if (notifyNow && validatePhoneId(phoneId)) {
359                    if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
360                        try {
361                            r.callback.onServiceStateChanged(
362                                    new ServiceState(mServiceState[phoneId]));
363                        } catch (RemoteException ex) {
364                            remove(r.binder);
365                        }
366                    }
367                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
368                        try {
369                            int gsmSignalStrength = mSignalStrength[phoneId]
370                                    .getGsmSignalStrength();
371                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
372                                    : gsmSignalStrength));
373                        } catch (RemoteException ex) {
374                            remove(r.binder);
375                        }
376                    }
377                    if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
378                        try {
379                            r.callback.onMessageWaitingIndicatorChanged(
380                                    mMessageWaiting[phoneId]);
381                        } catch (RemoteException ex) {
382                            remove(r.binder);
383                        }
384                    }
385                    if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
386                        try {
387                            r.callback.onCallForwardingIndicatorChanged(
388                                    mCallForwarding[phoneId]);
389                        } catch (RemoteException ex) {
390                            remove(r.binder);
391                        }
392                    }
393                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
394                        try {
395                            if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation = "
396                                    + mCellLocation[phoneId]);
397                            r.callback.onCellLocationChanged(
398                                    new Bundle(mCellLocation[phoneId]));
399                        } catch (RemoteException ex) {
400                            remove(r.binder);
401                        }
402                    }
403                    if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
404                        try {
405                            r.callback.onCallStateChanged(mCallState[phoneId],
406                                     mCallIncomingNumber[phoneId]);
407                        } catch (RemoteException ex) {
408                            remove(r.binder);
409                        }
410                    }
411                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
412                        try {
413                            r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
414                                mDataConnectionNetworkType[phoneId]);
415                        } catch (RemoteException ex) {
416                            remove(r.binder);
417                        }
418                    }
419                    if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
420                        try {
421                            r.callback.onDataActivity(mDataActivity[phoneId]);
422                        } catch (RemoteException ex) {
423                            remove(r.binder);
424                        }
425                    }
426                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
427                        try {
428                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
429                        } catch (RemoteException ex) {
430                            remove(r.binder);
431                        }
432                    }
433                    if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
434                        try {
435                            r.callback.onOtaspChanged(mOtaspMode);
436                        } catch (RemoteException ex) {
437                            remove(r.binder);
438                        }
439                    }
440                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
441                        try {
442                            if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo[" + phoneId + "] = "
443                                    + mCellInfo.get(phoneId));
444                            r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
445                        } catch (RemoteException ex) {
446                            remove(r.binder);
447                        }
448                    }
449                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) {
450                        try {
451                            r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo);
452                        } catch (RemoteException ex) {
453                            remove(r.binder);
454                        }
455                    }
456                    if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
457                        try {
458                            r.callback.onPreciseCallStateChanged(mPreciseCallState);
459                        } catch (RemoteException ex) {
460                            remove(r.binder);
461                        }
462                    }
463                    if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
464                        try {
465                            r.callback.onPreciseDataConnectionStateChanged(
466                                    mPreciseDataConnectionState);
467                        } catch (RemoteException ex) {
468                            remove(r.binder);
469                        }
470                    }
471                }
472            }
473        } else {
474            remove(callback.asBinder());
475        }
476    }
477
478    private void remove(IBinder binder) {
479        synchronized (mRecords) {
480            final int recordCount = mRecords.size();
481            for (int i = 0; i < recordCount; i++) {
482                if (mRecords.get(i).binder == binder) {
483                    mRecords.remove(i);
484                    return;
485                }
486            }
487        }
488    }
489
490    public void notifyCallState(int state, String incomingNumber) {
491        if (!checkNotifyPermission("notifyCallState()")) {
492            return;
493        }
494        synchronized (mRecords) {
495            for (Record r : mRecords) {
496                if (((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) &&
497                    (r.isLegacyApp == true)) {
498                    // FIXME: why does isLegacyApp need to be true?
499                    try {
500                        r.callback.onCallStateChanged(state, incomingNumber);
501                    } catch (RemoteException ex) {
502                        mRemoveList.add(r.binder);
503                    }
504                }
505            }
506            handleRemoveListLocked();
507        }
508        broadcastCallStateChanged(state, incomingNumber, mDefaultSubId);
509    }
510
511    public void notifyCallStateUsingSubId(long subId, int state, String incomingNumber) {
512        if (!checkNotifyPermission("notifyCallState()")) {
513            return;
514        }
515        if (VDBG) {
516            Slog.d(TAG, "notifyCallStateUsingSubId: subId=" + subId
517                + " state=" + state + " incomingNumber=" + incomingNumber);
518        }
519        synchronized (mRecords) {
520            int phoneId = SubscriptionManager.getPhoneId(subId);
521            if (validatePhoneId(phoneId)) {
522                mCallState[phoneId] = state;
523                mCallIncomingNumber[phoneId] = incomingNumber;
524                for (Record r : mRecords) {
525                    if (((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) &&
526                        (r.subId == subId) && (r.isLegacyApp == false)) {
527                        // FIXME: why isLegacyApp false?
528                        try {
529                            r.callback.onCallStateChanged(state, incomingNumber);
530                        } catch (RemoteException ex) {
531                            mRemoveList.add(r.binder);
532                        }
533                    }
534                }
535            }
536            handleRemoveListLocked();
537        }
538        broadcastCallStateChanged(state, incomingNumber, subId);
539    }
540
541     public void notifyServiceState(ServiceState state) {
542         notifyServiceStateUsingSubId(mDefaultSubId, state);
543     }
544
545    public void notifyServiceStateUsingSubId(long subId, ServiceState state) {
546        if (!checkNotifyPermission("notifyServiceState()")){
547            return;
548        }
549        if (subId == SubscriptionManager.DEFAULT_SUB_ID) {
550            subId = mDefaultSubId;
551            Slog.d(TAG, "notifyServiceStateUsingSubId: using mDefaultSubId=" + mDefaultSubId);
552        }
553        if (VDBG) {
554            Slog.d(TAG, "notifyServiceStateUsingSubId: subId=" + subId
555                + " state=" + state);
556        }
557        synchronized (mRecords) {
558            int phoneId = SubscriptionManager.getPhoneId(subId);
559            if (validatePhoneId(phoneId)) {
560                mServiceState[phoneId] = state;
561                for (Record r : mRecords) {
562                    // FIXME: use DEFAULT_SUB_ID instead??
563                    if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) &&
564                            (r.subId == subId)) {
565                        try {
566                            r.callback.onServiceStateChanged(new ServiceState(state));
567                        } catch (RemoteException ex) {
568                            mRemoveList.add(r.binder);
569                        }
570                    }
571                }
572            } else {
573                Slog.d(TAG, "notifyServiceStateUsingSubId: INVALID phoneId=" + phoneId);
574            }
575            handleRemoveListLocked();
576        }
577        broadcastServiceStateChanged(state, subId);
578    }
579
580    public void notifySignalStrength(SignalStrength signalStrength) {
581        notifySignalStrengthUsingSubId(mDefaultSubId, signalStrength);
582    }
583
584    public void notifySignalStrengthUsingSubId(long subId, SignalStrength signalStrength) {
585        if (!checkNotifyPermission("notifySignalStrength()")) {
586            return;
587        }
588        if (VDBG) {
589            Slog.d(TAG, "notifySignalStrengthUsingSubId: subId=" + subId
590                + " signalStrength=" + signalStrength);
591        }
592        synchronized (mRecords) {
593            int phoneId = SubscriptionManager.getPhoneId(subId);
594            if (validatePhoneId(phoneId)) {
595                mSignalStrength[phoneId] = signalStrength;
596                for (Record r : mRecords) {
597                    if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) &&
598                        (r.subId == subId)){
599                        try {
600                            r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
601                        } catch (RemoteException ex) {
602                            mRemoveList.add(r.binder);
603                        }
604                    }
605                    if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) &&
606                        (r.subId == subId)) {
607                        try {
608                            int gsmSignalStrength = signalStrength.getGsmSignalStrength();
609                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
610                                    : gsmSignalStrength));
611                        } catch (RemoteException ex) {
612                            mRemoveList.add(r.binder);
613                        }
614                    }
615                }
616            }
617            handleRemoveListLocked();
618        }
619        broadcastSignalStrengthChanged(signalStrength, subId);
620    }
621
622    public void notifyCellInfo(List<CellInfo> cellInfo) {
623         notifyCellInfoUsingSubId(mDefaultSubId, cellInfo);
624    }
625
626    public void notifyCellInfoUsingSubId(long subId, List<CellInfo> cellInfo) {
627        if (!checkNotifyPermission("notifyCellInfo()")) {
628            return;
629        }
630        if (VDBG) {
631            Slog.d(TAG, "notifyCellInfoUsingSubId: subId=" + subId
632                + " cellInfo=" + cellInfo);
633        }
634
635        synchronized (mRecords) {
636            int phoneId = SubscriptionManager.getPhoneId(subId);
637            if (validatePhoneId(phoneId)) {
638                mCellInfo.set(phoneId, cellInfo);
639                for (Record r : mRecords) {
640                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)
641                            && r.subId == subId) {
642                        try {
643                            if (DBG_LOC) {
644                                Slog.d(TAG, "notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
645                            }
646                            r.callback.onCellInfoChanged(cellInfo);
647                        } catch (RemoteException ex) {
648                            mRemoveList.add(r.binder);
649                        }
650                    }
651                }
652            }
653            handleRemoveListLocked();
654        }
655    }
656
657    public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) {
658        if (!checkNotifyPermission("notifyDataConnectionRealTimeInfo()")) {
659            return;
660        }
661
662        synchronized (mRecords) {
663            mDcRtInfo = dcRtInfo;
664            for (Record r : mRecords) {
665                if (validateEventsAndUserLocked(r,
666                        PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO)) {
667                    try {
668                        if (DBG_LOC) {
669                            Slog.d(TAG, "notifyDataConnectionRealTimeInfo: mDcRtInfo="
670                                    + mDcRtInfo + " r=" + r);
671                        }
672                        r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo);
673                    } catch (RemoteException ex) {
674                        mRemoveList.add(r.binder);
675                    }
676                }
677            }
678            handleRemoveListLocked();
679        }
680    }
681
682    public void notifyMessageWaitingChanged(boolean mwi) {
683        notifyMessageWaitingChangedUsingSubId(mDefaultSubId, mwi);
684    }
685
686    public void notifyMessageWaitingChangedUsingSubId(long subId, boolean mwi) {
687        if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
688            return;
689        }
690        if (VDBG) {
691            Slog.d(TAG, "notifyMessageWaitingChangedUsingSubId: subId=" + subId
692                + " mwi=" + mwi);
693        }
694        synchronized (mRecords) {
695            int phoneId = SubscriptionManager.getPhoneId(subId);
696            if (validatePhoneId(phoneId)) {
697                mMessageWaiting[phoneId] = mwi;
698                for (Record r : mRecords) {
699                    if (((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) &&
700                        (r.subId == subId)) {
701                        try {
702                            r.callback.onMessageWaitingIndicatorChanged(mwi);
703                        } catch (RemoteException ex) {
704                            mRemoveList.add(r.binder);
705                        }
706                    }
707                }
708            }
709            handleRemoveListLocked();
710        }
711    }
712
713    public void notifyCallForwardingChanged(boolean cfi) {
714        notifyCallForwardingChangedUsingSubId(mDefaultSubId, cfi);
715    }
716
717    public void notifyCallForwardingChangedUsingSubId(long subId, boolean cfi) {
718        if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
719            return;
720        }
721        if (VDBG) {
722            Slog.d(TAG, "notifyCallForwardingChangedUsingSubId: subId=" + subId
723                + " cfi=" + cfi);
724        }
725        synchronized (mRecords) {
726            int phoneId = SubscriptionManager.getPhoneId(subId);
727            if (validatePhoneId(phoneId)) {
728                mCallForwarding[phoneId] = cfi;
729                for (Record r : mRecords) {
730                    if (((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) &&
731                        (r.subId == subId)) {
732                        try {
733                            r.callback.onCallForwardingIndicatorChanged(cfi);
734                        } catch (RemoteException ex) {
735                            mRemoveList.add(r.binder);
736                        }
737                    }
738                }
739            }
740            handleRemoveListLocked();
741        }
742    }
743
744    public void notifyDataActivity(int state) {
745        notifyDataActivityUsingSubId(mDefaultSubId, state);
746    }
747
748    public void notifyDataActivityUsingSubId(long subId, int state) {
749        if (!checkNotifyPermission("notifyDataActivity()" )) {
750            return;
751        }
752        synchronized (mRecords) {
753            int phoneId = SubscriptionManager.getPhoneId(subId);
754            mDataActivity[phoneId] = state;
755            for (Record r : mRecords) {
756                if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
757                    try {
758                        r.callback.onDataActivity(state);
759                    } catch (RemoteException ex) {
760                        mRemoveList.add(r.binder);
761                    }
762                }
763            }
764            handleRemoveListLocked();
765        }
766    }
767
768    public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
769            String reason, String apn, String apnType, LinkProperties linkProperties,
770            NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
771        notifyDataConnectionUsingSubId(mDefaultSubId, state, isDataConnectivityPossible,
772            reason, apn, apnType, linkProperties,
773            networkCapabilities, networkType, roaming);
774    }
775
776    public void notifyDataConnectionUsingSubId(long subId, int state,
777            boolean isDataConnectivityPossible, String reason, String apn, String apnType,
778            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
779            int networkType, boolean roaming) {
780        if (!checkNotifyPermission("notifyDataConnection()" )) {
781            return;
782        }
783        if (VDBG) {
784            Slog.i(TAG, "notifyDataConnectionUsingSubId: subId=" + subId
785                + " state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible
786                + " reason='" + reason
787                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
788                + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords);
789        }
790        synchronized (mRecords) {
791            int phoneId = SubscriptionManager.getPhoneId(subId);
792            boolean modified = false;
793            if (state == TelephonyManager.DATA_CONNECTED) {
794                if (!mConnectedApns.contains(apnType)) {
795                    mConnectedApns.add(apnType);
796                    if (mDataConnectionState[phoneId] != state) {
797                        mDataConnectionState[phoneId] = state;
798                        modified = true;
799                    }
800                }
801            } else {
802                if (mConnectedApns.remove(apnType)) {
803                    if (mConnectedApns.isEmpty()) {
804                        mDataConnectionState[phoneId] = state;
805                        modified = true;
806                    } else {
807                        // leave mDataConnectionState as is and
808                        // send out the new status for the APN in question.
809                    }
810                }
811            }
812            mDataConnectionPossible[phoneId] = isDataConnectivityPossible;
813            mDataConnectionReason[phoneId] = reason;
814            mDataConnectionLinkProperties[phoneId] = linkProperties;
815            mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
816            if (mDataConnectionNetworkType[phoneId] != networkType) {
817                mDataConnectionNetworkType[phoneId] = networkType;
818                // need to tell registered listeners about the new network type
819                modified = true;
820            }
821            if (modified) {
822                if (DBG) {
823                    Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState[phoneId]
824                        + ", " + mDataConnectionNetworkType[phoneId] + ")");
825                }
826                for (Record r : mRecords) {
827                    if (((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) &&
828                            (r.subId == subId)) {
829                        try {
830                            Slog.d(TAG,"Notify data connection state changed on sub: " +
831                                    subId);
832                            r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
833                                    mDataConnectionNetworkType[phoneId]);
834                        } catch (RemoteException ex) {
835                            mRemoveList.add(r.binder);
836                        }
837                    }
838                }
839                handleRemoveListLocked();
840            }
841            mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
842                    apnType, apn, reason, linkProperties, "");
843            for (Record r : mRecords) {
844                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
845                    try {
846                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
847                    } catch (RemoteException ex) {
848                        mRemoveList.add(r.binder);
849                    }
850                }
851            }
852            handleRemoveListLocked();
853        }
854        broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
855                apnType, linkProperties, networkCapabilities, roaming, subId);
856        broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
857                linkProperties, "");
858    }
859
860    public void notifyDataConnectionFailed(String reason, String apnType) {
861         notifyDataConnectionFailedUsingSubId(mDefaultSubId, reason, apnType);
862    }
863
864    public void notifyDataConnectionFailedUsingSubId(long subId,
865            String reason, String apnType) {
866        if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
867            return;
868        }
869        if (VDBG) {
870            Slog.d(TAG, "notifyDataConnectionFailedUsingSubId: subId=" + subId
871                + " reason=" + reason + " apnType=" + apnType);
872        }
873        synchronized (mRecords) {
874            mPreciseDataConnectionState = new PreciseDataConnectionState(
875                    TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
876                    apnType, "", reason, null, "");
877            for (Record r : mRecords) {
878                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
879                    try {
880                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
881                    } catch (RemoteException ex) {
882                        mRemoveList.add(r.binder);
883                    }
884                }
885            }
886            handleRemoveListLocked();
887        }
888        broadcastDataConnectionFailed(reason, apnType, subId);
889        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
890                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
891    }
892
893    public void notifyCellLocation(Bundle cellLocation) {
894         notifyCellLocationUsingSubId(mDefaultSubId, cellLocation);
895    }
896
897    public void notifyCellLocationUsingSubId(long subId, Bundle cellLocation) {
898        Slog.d(TAG, "notifyCellLocationUsingSubId: subId=" + subId
899                + " cellLocation=" + cellLocation);
900        if (!checkNotifyPermission("notifyCellLocation()")) {
901            return;
902        }
903        if (VDBG) {
904            Slog.d(TAG, "notifyCellLocationUsingSubId: subId=" + subId
905                + " cellLocation=" + cellLocation);
906        }
907        synchronized (mRecords) {
908            int phoneId = SubscriptionManager.getPhoneId(subId);
909            if (validatePhoneId(phoneId)) {
910                mCellLocation[phoneId] = cellLocation;
911                for (Record r : mRecords) {
912                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)
913                            && r.subId == subId) {
914                        try {
915                            if (DBG_LOC) {
916                                Slog.d(TAG, "notifyCellLocation: cellLocation=" + cellLocation
917                                        + " r=" + r);
918                            }
919                            r.callback.onCellLocationChanged(new Bundle(cellLocation));
920                        } catch (RemoteException ex) {
921                            mRemoveList.add(r.binder);
922                        }
923                    }
924                }
925            }
926            handleRemoveListLocked();
927        }
928    }
929
930    public void notifyOtaspChanged(int otaspMode) {
931        if (!checkNotifyPermission("notifyOtaspChanged()" )) {
932            return;
933        }
934        synchronized (mRecords) {
935            mOtaspMode = otaspMode;
936            for (Record r : mRecords) {
937                if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
938                    try {
939                        r.callback.onOtaspChanged(otaspMode);
940                    } catch (RemoteException ex) {
941                        mRemoveList.add(r.binder);
942                    }
943                }
944            }
945            handleRemoveListLocked();
946        }
947    }
948
949    public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
950            int backgroundCallState) {
951        if (!checkNotifyPermission("notifyPreciseCallState()")) {
952            return;
953        }
954        synchronized (mRecords) {
955            mRingingCallState = ringingCallState;
956            mForegroundCallState = foregroundCallState;
957            mBackgroundCallState = backgroundCallState;
958            mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
959                    backgroundCallState,
960                    DisconnectCause.NOT_VALID,
961                    PreciseDisconnectCause.NOT_VALID);
962            for (Record r : mRecords) {
963                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
964                    try {
965                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
966                    } catch (RemoteException ex) {
967                        mRemoveList.add(r.binder);
968                    }
969                }
970            }
971            handleRemoveListLocked();
972        }
973        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
974                DisconnectCause.NOT_VALID,
975                PreciseDisconnectCause.NOT_VALID);
976    }
977
978    public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
979        if (!checkNotifyPermission("notifyDisconnectCause()")) {
980            return;
981        }
982        synchronized (mRecords) {
983            mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
984                    mBackgroundCallState, disconnectCause, preciseDisconnectCause);
985            for (Record r : mRecords) {
986                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
987                    try {
988                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
989                    } catch (RemoteException ex) {
990                        mRemoveList.add(r.binder);
991                    }
992                }
993            }
994            handleRemoveListLocked();
995        }
996        broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
997                mBackgroundCallState, disconnectCause, preciseDisconnectCause);
998    }
999
1000    public void notifyPreciseDataConnectionFailed(String reason, String apnType,
1001            String apn, String failCause) {
1002        if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
1003            return;
1004        }
1005        synchronized (mRecords) {
1006            mPreciseDataConnectionState = new PreciseDataConnectionState(
1007                    TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
1008                    apnType, apn, reason, null, failCause);
1009            for (Record r : mRecords) {
1010                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
1011                    try {
1012                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
1013                    } catch (RemoteException ex) {
1014                        mRemoveList.add(r.binder);
1015                    }
1016                }
1017            }
1018            handleRemoveListLocked();
1019        }
1020        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
1021                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
1022    }
1023
1024    public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
1025        if (!checkNotifyPermission("notifyVoLteServiceStateChanged()")) {
1026            return;
1027        }
1028        synchronized (mRecords) {
1029            mVoLteServiceState = lteState;
1030            for (Record r : mRecords) {
1031                if ((r.events & PhoneStateListener.LISTEN_VOLTE_STATE) != 0) {
1032                    try {
1033                        r.callback.onVoLteServiceStateChanged(
1034                                new VoLteServiceState(mVoLteServiceState));
1035                    } catch (RemoteException ex) {
1036                        mRemoveList.add(r.binder);
1037                    }
1038                }
1039            }
1040            handleRemoveListLocked();
1041        }
1042    }
1043
1044    @Override
1045    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1046        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1047                != PackageManager.PERMISSION_GRANTED) {
1048            pw.println("Permission Denial: can't dump telephony.registry from from pid="
1049                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1050            return;
1051        }
1052        synchronized (mRecords) {
1053            final int recordCount = mRecords.size();
1054            pw.println("last known state:");
1055            pw.println("  mCallState=" + mCallState);
1056            pw.println("  mCallIncomingNumber=" + mCallIncomingNumber);
1057            pw.println("  mServiceState=" + mServiceState);
1058            pw.println("  mSignalStrength=" + mSignalStrength);
1059            pw.println("  mMessageWaiting=" + mMessageWaiting);
1060            pw.println("  mCallForwarding=" + mCallForwarding);
1061            pw.println("  mDataActivity=" + mDataActivity);
1062            pw.println("  mDataConnectionState=" + mDataConnectionState);
1063            pw.println("  mDataConnectionPossible=" + mDataConnectionPossible);
1064            pw.println("  mDataConnectionReason=" + mDataConnectionReason);
1065            pw.println("  mDataConnectionApn=" + mDataConnectionApn);
1066            pw.println("  mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
1067            pw.println("  mDataConnectionNetworkCapabilities=" +
1068                    mDataConnectionNetworkCapabilities);
1069            pw.println("  mDefaultSubId=" + mDefaultSubId);
1070            pw.println("  mCellLocation=" + mCellLocation);
1071            pw.println("  mCellInfo=" + mCellInfo);
1072            pw.println("  mDcRtInfo=" + mDcRtInfo);
1073            pw.println("registrations: count=" + recordCount);
1074            for (Record r : mRecords) {
1075                pw.println("  " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
1076            }
1077        }
1078    }
1079
1080    //
1081    // the legacy intent broadcasting
1082    //
1083
1084    private void broadcastServiceStateChanged(ServiceState state, long subId) {
1085        long ident = Binder.clearCallingIdentity();
1086        try {
1087            mBatteryStats.notePhoneState(state.getState());
1088        } catch (RemoteException re) {
1089            // Can't do much
1090        } finally {
1091            Binder.restoreCallingIdentity(ident);
1092        }
1093
1094        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
1095        Bundle data = new Bundle();
1096        state.fillInNotifierBundle(data);
1097        intent.putExtras(data);
1098        // Pass the subscription along with the intent.
1099        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1100        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1101    }
1102
1103    private void broadcastSignalStrengthChanged(SignalStrength signalStrength, long subId) {
1104        long ident = Binder.clearCallingIdentity();
1105        try {
1106            mBatteryStats.notePhoneSignalStrength(signalStrength);
1107        } catch (RemoteException e) {
1108            /* The remote entity disappeared, we can safely ignore the exception. */
1109        } finally {
1110            Binder.restoreCallingIdentity(ident);
1111        }
1112
1113        Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
1114        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
1115        Bundle data = new Bundle();
1116        signalStrength.fillInNotifierBundle(data);
1117        intent.putExtras(data);
1118        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1119        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1120    }
1121
1122    private void broadcastCallStateChanged(int state, String incomingNumber, long subId) {
1123        long ident = Binder.clearCallingIdentity();
1124        try {
1125            if (state == TelephonyManager.CALL_STATE_IDLE) {
1126                mBatteryStats.notePhoneOff();
1127            } else {
1128                mBatteryStats.notePhoneOn();
1129            }
1130        } catch (RemoteException e) {
1131            /* The remote entity disappeared, we can safely ignore the exception. */
1132        } finally {
1133            Binder.restoreCallingIdentity(ident);
1134        }
1135
1136        Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
1137        intent.putExtra(PhoneConstants.STATE_KEY,
1138                DefaultPhoneNotifier.convertCallState(state).toString());
1139        if (!TextUtils.isEmpty(incomingNumber)) {
1140            intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
1141        }
1142        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1143        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
1144                android.Manifest.permission.READ_PHONE_STATE);
1145    }
1146
1147    private void broadcastDataConnectionStateChanged(int state,
1148            boolean isDataConnectivityPossible,
1149            String reason, String apn, String apnType, LinkProperties linkProperties,
1150            NetworkCapabilities networkCapabilities, boolean roaming, long subId) {
1151        // Note: not reporting to the battery stats service here, because the
1152        // status bar takes care of that after taking into account all of the
1153        // required info.
1154        Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
1155        intent.putExtra(PhoneConstants.STATE_KEY,
1156                DefaultPhoneNotifier.convertDataState(state).toString());
1157        if (!isDataConnectivityPossible) {
1158            intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
1159        }
1160        if (reason != null) {
1161            intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
1162        }
1163        if (linkProperties != null) {
1164            intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
1165            String iface = linkProperties.getInterfaceName();
1166            if (iface != null) {
1167                intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface);
1168            }
1169        }
1170        if (networkCapabilities != null) {
1171            intent.putExtra(PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY, networkCapabilities);
1172        }
1173        if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true);
1174
1175        intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
1176        intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
1177        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1178        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1179    }
1180
1181    private void broadcastDataConnectionFailed(String reason, String apnType,
1182            long subId) {
1183        Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
1184        intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason);
1185        intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
1186        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1187        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1188    }
1189
1190    private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
1191            int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
1192        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
1193        intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
1194        intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
1195        intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
1196        intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
1197        intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
1198        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
1199                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
1200    }
1201
1202    private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
1203            String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) {
1204        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
1205        intent.putExtra(PhoneConstants.STATE_KEY, state);
1206        intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
1207        if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
1208        if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
1209        if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
1210        if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
1211        if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
1212
1213        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
1214                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
1215    }
1216
1217    private boolean checkNotifyPermission(String method) {
1218        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
1219                == PackageManager.PERMISSION_GRANTED) {
1220            return true;
1221        }
1222        String msg = "Modify Phone State Permission Denial: " + method + " from pid="
1223                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
1224        if (DBG) Slog.w(TAG, msg);
1225        return false;
1226    }
1227
1228    private void checkListenerPermission(int events) {
1229        if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
1230            mContext.enforceCallingOrSelfPermission(
1231                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1232
1233        }
1234
1235        if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
1236            mContext.enforceCallingOrSelfPermission(
1237                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1238
1239        }
1240
1241        if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
1242            mContext.enforceCallingOrSelfPermission(
1243                    android.Manifest.permission.READ_PHONE_STATE, null);
1244        }
1245
1246        if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
1247            mContext.enforceCallingOrSelfPermission(
1248                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
1249
1250        }
1251    }
1252
1253    private void handleRemoveListLocked() {
1254        if (mRemoveList.size() > 0) {
1255            for (IBinder b: mRemoveList) {
1256                remove(b);
1257            }
1258            mRemoveList.clear();
1259        }
1260    }
1261
1262    private boolean validateEventsAndUserLocked(Record r, int events) {
1263        int foregroundUser;
1264        long callingIdentity = Binder.clearCallingIdentity();
1265        boolean valid = false;
1266        try {
1267            foregroundUser = ActivityManager.getCurrentUser();
1268            valid = r.callerUid ==  foregroundUser && (r.events & events) != 0;
1269            if (DBG | DBG_LOC) {
1270                Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid
1271                        + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
1272                        + " r.events=" + r.events + " events=" + events);
1273            }
1274        } finally {
1275            Binder.restoreCallingIdentity(callingIdentity);
1276        }
1277        return valid;
1278    }
1279
1280    private boolean validatePhoneId(int phoneId) {
1281        boolean valid = (phoneId >= 0) && (phoneId < mNumPhones);
1282        if (VDBG) Slog.d(TAG, "validatePhoneId: " + valid);
1283        return valid;
1284    }
1285}
1286