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