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