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