TelephonyRegistry.java revision a54bf6583380cf328b9858d942b4c387c6163f0f
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            if (!hasNotifySubscriptionInfoChangedOccurred) {
413                log("notifySubscriptionInfoChanged: first invocation mRecords.size="
414                        + mRecords.size());
415            }
416            hasNotifySubscriptionInfoChangedOccurred = true;
417            mRemoveList.clear();
418            for (Record r : mRecords) {
419                if (r.matchOnSubscriptionsChangedListener()) {
420                    try {
421                        if (VDBG) log("notifySubscriptionInfoChanged: call osc to r=" + r);
422                        r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
423                        if (VDBG) log("notifySubscriptionInfoChanged: done osc to r=" + r);
424                    } catch (RemoteException ex) {
425                        if (VDBG) log("notifySubscriptionInfoChanged: RemoteException r=" + r);
426                        mRemoveList.add(r.binder);
427                    }
428                }
429            }
430            handleRemoveListLocked();
431        }
432    }
433
434    @Override
435    public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
436            boolean notifyNow) {
437        listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
438                events, notifyNow);
439    }
440
441    @Override
442    public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback,
443            int events, boolean notifyNow) {
444        listen(pkgForDebug, callback, events, notifyNow, subId);
445    }
446
447    private void listen(String pkgForDebug, IPhoneStateListener callback, int events,
448            boolean notifyNow, int subId) {
449        int callerUid = UserHandle.getCallingUserId();
450        int myUid = UserHandle.myUserId();
451        if (VDBG) {
452            log("listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
453                + " notifyNow=" + notifyNow + " subId=" + subId + " myUid=" + myUid
454                + " callerUid=" + callerUid);
455        }
456
457        if (events != PhoneStateListener.LISTEN_NONE) {
458            /* Checks permission and throws Security exception */
459            checkListenerPermission(events);
460            synchronized (mRecords) {
461                // register
462                Record r = null;
463                find_and_add: {
464                    IBinder b = callback.asBinder();
465                    final int N = mRecords.size();
466                    for (int i = 0; i < N; i++) {
467                        r = mRecords.get(i);
468                        if (b == r.binder) {
469                            break find_and_add;
470                        }
471                    }
472                    r = new Record();
473                    r.binder = b;
474                    mRecords.add(r);
475                    if (DBG) log("listen: add new record");
476                }
477
478                r.callback = callback;
479                r.pkgForDebug = pkgForDebug;
480                r.callerUid = callerUid;
481                // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
482                // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
483                if (!SubscriptionManager.isValidSubscriptionId(subId)) {
484                    r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
485                 } else {//APP specify subID
486                    r.subId = subId;
487                }
488                r.phoneId = SubscriptionManager.getPhoneId(r.subId);
489
490                int phoneId = r.phoneId;
491                r.events = events;
492                if (DBG) {
493                    log("listen:  Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
494                }
495                if (VDBG) toStringLogSSC("listen");
496                if (notifyNow && validatePhoneId(phoneId)) {
497                    if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
498                        try {
499                            if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
500                            r.callback.onServiceStateChanged(
501                                    new ServiceState(mServiceState[phoneId]));
502                        } catch (RemoteException ex) {
503                            remove(r.binder);
504                        }
505                    }
506                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
507                        try {
508                            int gsmSignalStrength = mSignalStrength[phoneId]
509                                    .getGsmSignalStrength();
510                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
511                                    : gsmSignalStrength));
512                        } catch (RemoteException ex) {
513                            remove(r.binder);
514                        }
515                    }
516                    if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
517                        try {
518                            r.callback.onMessageWaitingIndicatorChanged(
519                                    mMessageWaiting[phoneId]);
520                        } catch (RemoteException ex) {
521                            remove(r.binder);
522                        }
523                    }
524                    if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
525                        try {
526                            r.callback.onCallForwardingIndicatorChanged(
527                                    mCallForwarding[phoneId]);
528                        } catch (RemoteException ex) {
529                            remove(r.binder);
530                        }
531                    }
532                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
533                        try {
534                            if (DBG_LOC) log("listen: mCellLocation = "
535                                    + mCellLocation[phoneId]);
536                            r.callback.onCellLocationChanged(
537                                    new Bundle(mCellLocation[phoneId]));
538                        } catch (RemoteException ex) {
539                            remove(r.binder);
540                        }
541                    }
542                    if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
543                        try {
544                            r.callback.onCallStateChanged(mCallState[phoneId],
545                                     mCallIncomingNumber[phoneId]);
546                        } catch (RemoteException ex) {
547                            remove(r.binder);
548                        }
549                    }
550                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
551                        try {
552                            r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
553                                mDataConnectionNetworkType[phoneId]);
554                        } catch (RemoteException ex) {
555                            remove(r.binder);
556                        }
557                    }
558                    if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
559                        try {
560                            r.callback.onDataActivity(mDataActivity[phoneId]);
561                        } catch (RemoteException ex) {
562                            remove(r.binder);
563                        }
564                    }
565                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
566                        try {
567                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
568                        } catch (RemoteException ex) {
569                            remove(r.binder);
570                        }
571                    }
572                    if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
573                        try {
574                            r.callback.onOtaspChanged(mOtaspMode);
575                        } catch (RemoteException ex) {
576                            remove(r.binder);
577                        }
578                    }
579                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
580                        try {
581                            if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
582                                    + mCellInfo.get(phoneId));
583                            r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
584                        } catch (RemoteException ex) {
585                            remove(r.binder);
586                        }
587                    }
588                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) {
589                        try {
590                            r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo);
591                        } catch (RemoteException ex) {
592                            remove(r.binder);
593                        }
594                    }
595                    if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
596                        try {
597                            r.callback.onPreciseCallStateChanged(mPreciseCallState);
598                        } catch (RemoteException ex) {
599                            remove(r.binder);
600                        }
601                    }
602                    if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
603                        try {
604                            r.callback.onPreciseDataConnectionStateChanged(
605                                    mPreciseDataConnectionState);
606                        } catch (RemoteException ex) {
607                            remove(r.binder);
608                        }
609                    }
610                }
611            }
612        } else {
613            if(DBG) log("listen: Unregister");
614            remove(callback.asBinder());
615        }
616    }
617
618    private void remove(IBinder binder) {
619        synchronized (mRecords) {
620            final int recordCount = mRecords.size();
621            for (int i = 0; i < recordCount; i++) {
622                if (mRecords.get(i).binder == binder) {
623                    if (VDBG) log("remove: binder=" + binder);
624                    mRecords.remove(i);
625                    return;
626                }
627            }
628        }
629    }
630
631    public void notifyCallState(int state, String incomingNumber) {
632        if (!checkNotifyPermission("notifyCallState()")) {
633            return;
634        }
635
636        if (VDBG) {
637            log("notifyCallState: state=" + state + " incomingNumber=" + incomingNumber);
638        }
639
640        synchronized (mRecords) {
641            for (Record r : mRecords) {
642                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
643                        (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
644                    try {
645                        r.callback.onCallStateChanged(state, incomingNumber);
646                    } catch (RemoteException ex) {
647                        mRemoveList.add(r.binder);
648                    }
649                }
650            }
651            handleRemoveListLocked();
652        }
653        broadcastCallStateChanged(state, incomingNumber,
654                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
655    }
656
657    public void notifyCallStateForSubscriber(int subId, int state, String incomingNumber) {
658        if (!checkNotifyPermission("notifyCallState()")) {
659            return;
660        }
661        if (VDBG) {
662            log("notifyCallStateForSubscriber: subId=" + subId
663                + " state=" + state + " incomingNumber=" + incomingNumber);
664        }
665        synchronized (mRecords) {
666            int phoneId = SubscriptionManager.getPhoneId(subId);
667            if (validatePhoneId(phoneId)) {
668                mCallState[phoneId] = state;
669                mCallIncomingNumber[phoneId] = incomingNumber;
670                for (Record r : mRecords) {
671                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
672                            (r.subId == subId) &&
673                            (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
674                        try {
675                            r.callback.onCallStateChanged(state, incomingNumber);
676                        } catch (RemoteException ex) {
677                            mRemoveList.add(r.binder);
678                        }
679                    }
680                }
681            }
682            handleRemoveListLocked();
683        }
684        broadcastCallStateChanged(state, incomingNumber, subId);
685    }
686
687    public void notifyServiceStateForPhoneId(int phoneId, int subId, ServiceState state) {
688        if (!checkNotifyPermission("notifyServiceState()")){
689            return;
690        }
691
692        synchronized (mRecords) {
693            if (VDBG) {
694                log("notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
695                    + " state=" + state);
696            }
697            if (validatePhoneId(phoneId)) {
698                mServiceState[phoneId] = state;
699                logServiceStateChanged("notifyServiceStateForSubscriber", subId, phoneId, state);
700                if (VDBG) toStringLogSSC("notifyServiceStateForSubscriber");
701
702                for (Record r : mRecords) {
703                    if (VDBG) {
704                        log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
705                                + " phoneId=" + phoneId + " state=" + state);
706                    }
707                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SERVICE_STATE) &&
708                            idMatch(r.subId, subId, phoneId)) {
709                        try {
710                            if (DBG) {
711                                log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
712                                        + " subId=" + subId + " phoneId=" + phoneId
713                                        + " state=" + state);
714                            }
715                            r.callback.onServiceStateChanged(new ServiceState(state));
716                        } catch (RemoteException ex) {
717                            mRemoveList.add(r.binder);
718                        }
719                    }
720                }
721            } else {
722                log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId);
723            }
724            handleRemoveListLocked();
725        }
726        broadcastServiceStateChanged(state, subId);
727    }
728
729    public void notifySignalStrength(SignalStrength signalStrength) {
730        notifySignalStrengthForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
731                signalStrength);
732    }
733
734    public void notifySignalStrengthForSubscriber(int subId, SignalStrength signalStrength) {
735        if (!checkNotifyPermission("notifySignalStrength()")) {
736            return;
737        }
738        if (VDBG) {
739            log("notifySignalStrengthForSubscriber: subId=" + subId
740                + " signalStrength=" + signalStrength);
741            toStringLogSSC("notifySignalStrengthForSubscriber");
742        }
743        synchronized (mRecords) {
744            int phoneId = SubscriptionManager.getPhoneId(subId);
745            if (validatePhoneId(phoneId)) {
746                if (VDBG) log("notifySignalStrengthForSubscriber: valid phoneId=" + phoneId);
747                mSignalStrength[phoneId] = signalStrength;
748                for (Record r : mRecords) {
749                    if (VDBG) {
750                        log("notifySignalStrengthForSubscriber: r=" + r + " subId=" + subId
751                                + " phoneId=" + phoneId + " ss=" + signalStrength);
752                    }
753                    if (r.matchPhoneStateListenerEvent(
754                                PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) &&
755                            idMatch(r.subId, subId, phoneId)) {
756                        try {
757                            if (DBG) {
758                                log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
759                                        + " subId=" + subId + " phoneId=" + phoneId
760                                        + " ss=" + signalStrength);
761                            }
762                            r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
763                        } catch (RemoteException ex) {
764                            mRemoveList.add(r.binder);
765                        }
766                    }
767                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) &&
768                            idMatch(r.subId, subId, phoneId)){
769                        try {
770                            int gsmSignalStrength = signalStrength.getGsmSignalStrength();
771                            int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
772                            if (DBG) {
773                                log("notifySignalStrengthForSubscriber: callback.onSS r=" + r
774                                        + " subId=" + subId + " phoneId=" + phoneId
775                                        + " gsmSS=" + gsmSignalStrength + " ss=" + ss);
776                            }
777                            r.callback.onSignalStrengthChanged(ss);
778                        } catch (RemoteException ex) {
779                            mRemoveList.add(r.binder);
780                        }
781                    }
782                }
783            } else {
784                log("notifySignalStrengthForSubscriber: invalid phoneId=" + phoneId);
785            }
786            handleRemoveListLocked();
787        }
788        broadcastSignalStrengthChanged(signalStrength, subId);
789    }
790
791    public void notifyCellInfo(List<CellInfo> cellInfo) {
792         notifyCellInfoForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellInfo);
793    }
794
795    public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) {
796        if (!checkNotifyPermission("notifyCellInfo()")) {
797            return;
798        }
799        if (VDBG) {
800            log("notifyCellInfoForSubscriber: subId=" + subId
801                + " cellInfo=" + cellInfo);
802        }
803
804        synchronized (mRecords) {
805            int phoneId = SubscriptionManager.getPhoneId(subId);
806            if (validatePhoneId(phoneId)) {
807                mCellInfo.set(phoneId, cellInfo);
808                for (Record r : mRecords) {
809                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
810                            idMatch(r.subId, subId, phoneId)) {
811                        try {
812                            if (DBG_LOC) {
813                                log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
814                            }
815                            r.callback.onCellInfoChanged(cellInfo);
816                        } catch (RemoteException ex) {
817                            mRemoveList.add(r.binder);
818                        }
819                    }
820                }
821            }
822            handleRemoveListLocked();
823        }
824    }
825
826    public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) {
827        if (!checkNotifyPermission("notifyDataConnectionRealTimeInfo()")) {
828            return;
829        }
830
831        synchronized (mRecords) {
832            mDcRtInfo = dcRtInfo;
833            for (Record r : mRecords) {
834                if (validateEventsAndUserLocked(r,
835                        PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO)) {
836                    try {
837                        if (DBG_LOC) {
838                            log("notifyDataConnectionRealTimeInfo: mDcRtInfo="
839                                    + mDcRtInfo + " r=" + r);
840                        }
841                        r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo);
842                    } catch (RemoteException ex) {
843                        mRemoveList.add(r.binder);
844                    }
845                }
846            }
847            handleRemoveListLocked();
848        }
849    }
850
851    @Override
852    public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
853        if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
854            return;
855        }
856        if (VDBG) {
857            log("notifyMessageWaitingChangedForSubscriberPhoneID: subId=" + phoneId
858                + " mwi=" + mwi);
859        }
860        synchronized (mRecords) {
861            if (validatePhoneId(phoneId)) {
862                mMessageWaiting[phoneId] = mwi;
863                for (Record r : mRecords) {
864                    if (r.matchPhoneStateListenerEvent(
865                            PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) &&
866                            idMatch(r.subId, subId, phoneId)) {
867                        try {
868                            r.callback.onMessageWaitingIndicatorChanged(mwi);
869                        } catch (RemoteException ex) {
870                            mRemoveList.add(r.binder);
871                        }
872                    }
873                }
874            }
875            handleRemoveListLocked();
876        }
877    }
878
879    public void notifyCallForwardingChanged(boolean cfi) {
880        notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cfi);
881    }
882
883    public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) {
884        if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
885            return;
886        }
887        if (VDBG) {
888            log("notifyCallForwardingChangedForSubscriber: subId=" + subId
889                + " cfi=" + cfi);
890        }
891        synchronized (mRecords) {
892            int phoneId = SubscriptionManager.getPhoneId(subId);
893            if (validatePhoneId(phoneId)) {
894                mCallForwarding[phoneId] = cfi;
895                for (Record r : mRecords) {
896                    if (r.matchPhoneStateListenerEvent(
897                            PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) &&
898                            idMatch(r.subId, subId, phoneId)) {
899                        try {
900                            r.callback.onCallForwardingIndicatorChanged(cfi);
901                        } catch (RemoteException ex) {
902                            mRemoveList.add(r.binder);
903                        }
904                    }
905                }
906            }
907            handleRemoveListLocked();
908        }
909    }
910
911    public void notifyDataActivity(int state) {
912        notifyDataActivityForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state);
913    }
914
915    public void notifyDataActivityForSubscriber(int subId, int state) {
916        if (!checkNotifyPermission("notifyDataActivity()" )) {
917            return;
918        }
919        synchronized (mRecords) {
920            int phoneId = SubscriptionManager.getPhoneId(subId);
921            if (validatePhoneId(phoneId)) {
922                mDataActivity[phoneId] = state;
923                for (Record r : mRecords) {
924                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY)) {
925                        try {
926                            r.callback.onDataActivity(state);
927                        } catch (RemoteException ex) {
928                            mRemoveList.add(r.binder);
929                        }
930                    }
931                }
932            }
933            handleRemoveListLocked();
934        }
935    }
936
937    public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
938            String reason, String apn, String apnType, LinkProperties linkProperties,
939            NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
940        notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state,
941            isDataConnectivityPossible,reason, apn, apnType, linkProperties,
942            networkCapabilities, networkType, roaming);
943    }
944
945    public void notifyDataConnectionForSubscriber(int subId, int state,
946            boolean isDataConnectivityPossible, String reason, String apn, String apnType,
947            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
948            int networkType, boolean roaming) {
949        if (!checkNotifyPermission("notifyDataConnection()" )) {
950            return;
951        }
952        if (VDBG) {
953            log("notifyDataConnectionForSubscriber: subId=" + subId
954                + " state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible
955                + " reason='" + reason
956                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
957                + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords);
958        }
959        synchronized (mRecords) {
960            int phoneId = SubscriptionManager.getPhoneId(subId);
961            if (validatePhoneId(phoneId)) {
962                boolean modified = false;
963                if (state == TelephonyManager.DATA_CONNECTED) {
964                    if (!mConnectedApns.contains(apnType)) {
965                        mConnectedApns.add(apnType);
966                        if (mDataConnectionState[phoneId] != state) {
967                            mDataConnectionState[phoneId] = state;
968                            modified = true;
969                        }
970                    }
971                } else {
972                    if (mConnectedApns.remove(apnType)) {
973                        if (mConnectedApns.isEmpty()) {
974                            mDataConnectionState[phoneId] = state;
975                            modified = true;
976                        } else {
977                            // leave mDataConnectionState as is and
978                            // send out the new status for the APN in question.
979                        }
980                    }
981                }
982                mDataConnectionPossible[phoneId] = isDataConnectivityPossible;
983                mDataConnectionReason[phoneId] = reason;
984                mDataConnectionLinkProperties[phoneId] = linkProperties;
985                mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
986                if (mDataConnectionNetworkType[phoneId] != networkType) {
987                    mDataConnectionNetworkType[phoneId] = networkType;
988                    // need to tell registered listeners about the new network type
989                    modified = true;
990                }
991                if (modified) {
992                    if (DBG) {
993                        log("onDataConnectionStateChanged(" + mDataConnectionState[phoneId]
994                            + ", " + mDataConnectionNetworkType[phoneId] + ")");
995                    }
996                    for (Record r : mRecords) {
997                        if (r.matchPhoneStateListenerEvent(
998                                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) &&
999                                idMatch(r.subId, subId, phoneId)) {
1000                            try {
1001                                log("Notify data connection state changed on sub: " +
1002                                        subId);
1003                                r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
1004                                        mDataConnectionNetworkType[phoneId]);
1005                            } catch (RemoteException ex) {
1006                                mRemoveList.add(r.binder);
1007                            }
1008                        }
1009                    }
1010                    handleRemoveListLocked();
1011                }
1012                mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
1013                        apnType, apn, reason, linkProperties, "");
1014                for (Record r : mRecords) {
1015                    if (r.matchPhoneStateListenerEvent(
1016                            PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
1017                        try {
1018                            r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
1019                        } catch (RemoteException ex) {
1020                            mRemoveList.add(r.binder);
1021                        }
1022                    }
1023                }
1024            }
1025            handleRemoveListLocked();
1026        }
1027        broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
1028                apnType, linkProperties, networkCapabilities, roaming, subId);
1029        broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
1030                linkProperties, "");
1031    }
1032
1033    public void notifyDataConnectionFailed(String reason, String apnType) {
1034         notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
1035                 reason, apnType);
1036    }
1037
1038    public void notifyDataConnectionFailedForSubscriber(int subId,
1039            String reason, String apnType) {
1040        if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
1041            return;
1042        }
1043        if (VDBG) {
1044            log("notifyDataConnectionFailedForSubscriber: subId=" + subId
1045                + " reason=" + reason + " apnType=" + apnType);
1046        }
1047        synchronized (mRecords) {
1048            mPreciseDataConnectionState = new PreciseDataConnectionState(
1049                    TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
1050                    apnType, "", reason, null, "");
1051            for (Record r : mRecords) {
1052                if (r.matchPhoneStateListenerEvent(
1053                        PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
1054                    try {
1055                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
1056                    } catch (RemoteException ex) {
1057                        mRemoveList.add(r.binder);
1058                    }
1059                }
1060            }
1061            handleRemoveListLocked();
1062        }
1063        broadcastDataConnectionFailed(reason, apnType, subId);
1064        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
1065                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
1066    }
1067
1068    public void notifyCellLocation(Bundle cellLocation) {
1069         notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
1070    }
1071
1072    public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
1073        log("notifyCellLocationForSubscriber: subId=" + subId
1074                + " cellLocation=" + cellLocation);
1075        if (!checkNotifyPermission("notifyCellLocation()")) {
1076            return;
1077        }
1078        if (VDBG) {
1079            log("notifyCellLocationForSubscriber: subId=" + subId
1080                + " cellLocation=" + cellLocation);
1081        }
1082        synchronized (mRecords) {
1083            int phoneId = SubscriptionManager.getPhoneId(subId);
1084            if (validatePhoneId(phoneId)) {
1085                mCellLocation[phoneId] = cellLocation;
1086                for (Record r : mRecords) {
1087                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
1088                            idMatch(r.subId, subId, phoneId)) {
1089                        try {
1090                            if (DBG_LOC) {
1091                                log("notifyCellLocation: cellLocation=" + cellLocation
1092                                        + " r=" + r);
1093                            }
1094                            r.callback.onCellLocationChanged(new Bundle(cellLocation));
1095                        } catch (RemoteException ex) {
1096                            mRemoveList.add(r.binder);
1097                        }
1098                    }
1099                }
1100            }
1101            handleRemoveListLocked();
1102        }
1103    }
1104
1105    public void notifyOtaspChanged(int otaspMode) {
1106        if (!checkNotifyPermission("notifyOtaspChanged()" )) {
1107            return;
1108        }
1109        synchronized (mRecords) {
1110            mOtaspMode = otaspMode;
1111            for (Record r : mRecords) {
1112                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_OTASP_CHANGED)) {
1113                    try {
1114                        r.callback.onOtaspChanged(otaspMode);
1115                    } catch (RemoteException ex) {
1116                        mRemoveList.add(r.binder);
1117                    }
1118                }
1119            }
1120            handleRemoveListLocked();
1121        }
1122    }
1123
1124    public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
1125            int backgroundCallState) {
1126        if (!checkNotifyPermission("notifyPreciseCallState()")) {
1127            return;
1128        }
1129        synchronized (mRecords) {
1130            mRingingCallState = ringingCallState;
1131            mForegroundCallState = foregroundCallState;
1132            mBackgroundCallState = backgroundCallState;
1133            mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
1134                    backgroundCallState,
1135                    DisconnectCause.NOT_VALID,
1136                    PreciseDisconnectCause.NOT_VALID);
1137            for (Record r : mRecords) {
1138                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) {
1139                    try {
1140                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
1141                    } catch (RemoteException ex) {
1142                        mRemoveList.add(r.binder);
1143                    }
1144                }
1145            }
1146            handleRemoveListLocked();
1147        }
1148        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
1149                DisconnectCause.NOT_VALID,
1150                PreciseDisconnectCause.NOT_VALID);
1151    }
1152
1153    public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
1154        if (!checkNotifyPermission("notifyDisconnectCause()")) {
1155            return;
1156        }
1157        synchronized (mRecords) {
1158            mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
1159                    mBackgroundCallState, disconnectCause, preciseDisconnectCause);
1160            for (Record r : mRecords) {
1161                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) {
1162                    try {
1163                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
1164                    } catch (RemoteException ex) {
1165                        mRemoveList.add(r.binder);
1166                    }
1167                }
1168            }
1169            handleRemoveListLocked();
1170        }
1171        broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
1172                mBackgroundCallState, disconnectCause, preciseDisconnectCause);
1173    }
1174
1175    public void notifyPreciseDataConnectionFailed(String reason, String apnType,
1176            String apn, String failCause) {
1177        if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
1178            return;
1179        }
1180        synchronized (mRecords) {
1181            mPreciseDataConnectionState = new PreciseDataConnectionState(
1182                    TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
1183                    apnType, apn, reason, null, failCause);
1184            for (Record r : mRecords) {
1185                if (r.matchPhoneStateListenerEvent(
1186                        PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
1187                    try {
1188                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
1189                    } catch (RemoteException ex) {
1190                        mRemoveList.add(r.binder);
1191                    }
1192                }
1193            }
1194            handleRemoveListLocked();
1195        }
1196        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
1197                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
1198    }
1199
1200    public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
1201        if (!checkNotifyPermission("notifyVoLteServiceStateChanged()")) {
1202            return;
1203        }
1204        synchronized (mRecords) {
1205            mVoLteServiceState = lteState;
1206            for (Record r : mRecords) {
1207                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_VOLTE_STATE)) {
1208                    try {
1209                        r.callback.onVoLteServiceStateChanged(
1210                                new VoLteServiceState(mVoLteServiceState));
1211                    } catch (RemoteException ex) {
1212                        mRemoveList.add(r.binder);
1213                    }
1214                }
1215            }
1216            handleRemoveListLocked();
1217        }
1218    }
1219
1220    public void notifyOemHookRawEventForSubscriber(int subId, byte[] rawData) {
1221        if (!checkNotifyPermission("notifyOemHookRawEventForSubscriber")) {
1222            return;
1223        }
1224
1225        synchronized (mRecords) {
1226            for (Record r : mRecords) {
1227                if (VDBG) {
1228                    log("notifyOemHookRawEventForSubscriber:  r=" + r + " subId=" + subId);
1229                }
1230                if ((r.matchPhoneStateListenerEvent(
1231                        PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT)) &&
1232                        ((r.subId == subId) ||
1233                        (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID))) {
1234                    try {
1235                        r.callback.onOemHookRawEvent(rawData);
1236                    } catch (RemoteException ex) {
1237                        mRemoveList.add(r.binder);
1238                    }
1239                }
1240            }
1241            handleRemoveListLocked();
1242        }
1243    }
1244
1245    @Override
1246    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1247        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1248                != PackageManager.PERMISSION_GRANTED) {
1249            pw.println("Permission Denial: can't dump telephony.registry from from pid="
1250                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1251            return;
1252        }
1253        synchronized (mRecords) {
1254            final int recordCount = mRecords.size();
1255            pw.println("last known state:");
1256            for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1257                pw.println("  Phone Id=" + i);
1258                pw.println("  mCallState=" + mCallState[i]);
1259                pw.println("  mCallIncomingNumber=" + mCallIncomingNumber[i]);
1260                pw.println("  mServiceState=" + mServiceState[i]);
1261                pw.println("  mSignalStrength=" + mSignalStrength[i]);
1262                pw.println("  mMessageWaiting=" + mMessageWaiting[i]);
1263                pw.println("  mCallForwarding=" + mCallForwarding[i]);
1264                pw.println("  mDataActivity=" + mDataActivity[i]);
1265                pw.println("  mDataConnectionState=" + mDataConnectionState[i]);
1266                pw.println("  mDataConnectionPossible=" + mDataConnectionPossible[i]);
1267                pw.println("  mDataConnectionReason=" + mDataConnectionReason[i]);
1268                pw.println("  mDataConnectionApn=" + mDataConnectionApn[i]);
1269                pw.println("  mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]);
1270                pw.println("  mDataConnectionNetworkCapabilities=" +
1271                        mDataConnectionNetworkCapabilities[i]);
1272                pw.println("  mCellLocation=" + mCellLocation[i]);
1273                pw.println("  mCellInfo=" + mCellInfo.get(i));
1274            }
1275            pw.println("  mDcRtInfo=" + mDcRtInfo);
1276            pw.println("registrations: count=" + recordCount);
1277            for (Record r : mRecords) {
1278                pw.println("  " + r);
1279            }
1280        }
1281    }
1282
1283    //
1284    // the legacy intent broadcasting
1285    //
1286
1287    private void broadcastServiceStateChanged(ServiceState state, int subId) {
1288        long ident = Binder.clearCallingIdentity();
1289        try {
1290            mBatteryStats.notePhoneState(state.getState());
1291        } catch (RemoteException re) {
1292            // Can't do much
1293        } finally {
1294            Binder.restoreCallingIdentity(ident);
1295        }
1296
1297        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
1298        Bundle data = new Bundle();
1299        state.fillInNotifierBundle(data);
1300        intent.putExtras(data);
1301        // Pass the subscription along with the intent.
1302        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1303        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1304    }
1305
1306    private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int subId) {
1307        long ident = Binder.clearCallingIdentity();
1308        try {
1309            mBatteryStats.notePhoneSignalStrength(signalStrength);
1310        } catch (RemoteException e) {
1311            /* The remote entity disappeared, we can safely ignore the exception. */
1312        } finally {
1313            Binder.restoreCallingIdentity(ident);
1314        }
1315
1316        Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
1317        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
1318        Bundle data = new Bundle();
1319        signalStrength.fillInNotifierBundle(data);
1320        intent.putExtras(data);
1321        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1322        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1323    }
1324
1325    private void broadcastCallStateChanged(int state, String incomingNumber, int subId) {
1326        long ident = Binder.clearCallingIdentity();
1327        try {
1328            if (state == TelephonyManager.CALL_STATE_IDLE) {
1329                mBatteryStats.notePhoneOff();
1330            } else {
1331                mBatteryStats.notePhoneOn();
1332            }
1333        } catch (RemoteException e) {
1334            /* The remote entity disappeared, we can safely ignore the exception. */
1335        } finally {
1336            Binder.restoreCallingIdentity(ident);
1337        }
1338
1339        Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
1340        intent.putExtra(PhoneConstants.STATE_KEY,
1341                DefaultPhoneNotifier.convertCallState(state).toString());
1342        if (!TextUtils.isEmpty(incomingNumber)) {
1343            intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
1344        }
1345        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1346        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
1347                android.Manifest.permission.READ_PHONE_STATE);
1348    }
1349
1350    private void broadcastDataConnectionStateChanged(int state,
1351            boolean isDataConnectivityPossible,
1352            String reason, String apn, String apnType, LinkProperties linkProperties,
1353            NetworkCapabilities networkCapabilities, boolean roaming, int subId) {
1354        // Note: not reporting to the battery stats service here, because the
1355        // status bar takes care of that after taking into account all of the
1356        // required info.
1357        Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
1358        intent.putExtra(PhoneConstants.STATE_KEY,
1359                DefaultPhoneNotifier.convertDataState(state).toString());
1360        if (!isDataConnectivityPossible) {
1361            intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
1362        }
1363        if (reason != null) {
1364            intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
1365        }
1366        if (linkProperties != null) {
1367            intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
1368            String iface = linkProperties.getInterfaceName();
1369            if (iface != null) {
1370                intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface);
1371            }
1372        }
1373        if (networkCapabilities != null) {
1374            intent.putExtra(PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY, networkCapabilities);
1375        }
1376        if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true);
1377
1378        intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
1379        intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
1380        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1381        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1382    }
1383
1384    private void broadcastDataConnectionFailed(String reason, String apnType,
1385            int subId) {
1386        Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
1387        intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason);
1388        intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
1389        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
1390        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1391    }
1392
1393    private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
1394            int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
1395        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
1396        intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
1397        intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
1398        intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
1399        intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
1400        intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
1401        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
1402                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
1403    }
1404
1405    private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
1406            String apnType, String apn, String reason, LinkProperties linkProperties,
1407            String failCause) {
1408        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
1409        intent.putExtra(PhoneConstants.STATE_KEY, state);
1410        intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
1411        if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
1412        if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
1413        if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
1414        if (linkProperties != null) {
1415            intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY,linkProperties);
1416        }
1417        if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
1418
1419        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
1420                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
1421    }
1422
1423    private boolean checkNotifyPermission(String method) {
1424        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
1425                == PackageManager.PERMISSION_GRANTED) {
1426            return true;
1427        }
1428        String msg = "Modify Phone State Permission Denial: " + method + " from pid="
1429                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
1430        if (DBG) log(msg);
1431        return false;
1432    }
1433
1434    private void checkListenerPermission(int events) {
1435        if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
1436            mContext.enforceCallingOrSelfPermission(
1437                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1438
1439        }
1440
1441        if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
1442            mContext.enforceCallingOrSelfPermission(
1443                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1444
1445        }
1446
1447        if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
1448            mContext.enforceCallingOrSelfPermission(
1449                    android.Manifest.permission.READ_PHONE_STATE, null);
1450        }
1451
1452        if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
1453            mContext.enforceCallingOrSelfPermission(
1454                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
1455
1456        }
1457
1458        if ((events & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) {
1459            mContext.enforceCallingOrSelfPermission(
1460                    android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
1461        }
1462    }
1463
1464    private void handleRemoveListLocked() {
1465        int size = mRemoveList.size();
1466        if (VDBG) log("handleRemoveListLocked: mRemoveList.size()=" + size);
1467        if (size > 0) {
1468            for (IBinder b: mRemoveList) {
1469                remove(b);
1470            }
1471            mRemoveList.clear();
1472        }
1473    }
1474
1475    private boolean validateEventsAndUserLocked(Record r, int events) {
1476        int foregroundUser;
1477        long callingIdentity = Binder.clearCallingIdentity();
1478        boolean valid = false;
1479        try {
1480            foregroundUser = ActivityManager.getCurrentUser();
1481            valid = r.callerUid ==  foregroundUser && r.matchPhoneStateListenerEvent(events);
1482            if (DBG | DBG_LOC) {
1483                log("validateEventsAndUserLocked: valid=" + valid
1484                        + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
1485                        + " r.events=" + r.events + " events=" + events);
1486            }
1487        } finally {
1488            Binder.restoreCallingIdentity(callingIdentity);
1489        }
1490        return valid;
1491    }
1492
1493    private boolean validatePhoneId(int phoneId) {
1494        boolean valid = (phoneId >= 0) && (phoneId < mNumPhones);
1495        if (VDBG) log("validatePhoneId: " + valid);
1496        return valid;
1497    }
1498
1499    private static void log(String s) {
1500        Rlog.d(TAG, s);
1501    }
1502
1503    private static class LogSSC {
1504        private Time mTime;
1505        private String mS;
1506        private int mSubId;
1507        private int mPhoneId;
1508        private ServiceState mState;
1509
1510        public void set(Time t, String s, int subId, int phoneId, ServiceState state) {
1511            mTime = t; mS = s; mSubId = subId; mPhoneId = phoneId; mState = state;
1512        }
1513
1514        @Override
1515        public String toString() {
1516            return mS + " Time " + mTime.toString() + " mSubId " + mSubId + " mPhoneId "
1517                    + mPhoneId + "  mState " + mState;
1518        }
1519    }
1520
1521    private LogSSC logSSC [] = new LogSSC[10];
1522    private int next = 0;
1523
1524    private void logServiceStateChanged(String s, int subId, int phoneId, ServiceState state) {
1525        if (logSSC == null || logSSC.length == 0) {
1526            return;
1527        }
1528        if (logSSC[next] == null) {
1529            logSSC[next] = new LogSSC();
1530        }
1531        Time t = new Time();
1532        t.setToNow();
1533        logSSC[next].set(t, s, subId, phoneId, state);
1534        if (++next >= logSSC.length) {
1535            next = 0;
1536        }
1537    }
1538
1539    private void toStringLogSSC(String prompt) {
1540        if (logSSC == null || logSSC.length == 0 || (next == 0 && logSSC[next] == null)) {
1541            log(prompt + ": logSSC is empty");
1542        } else {
1543            // There is at least one element
1544            log(prompt + ": logSSC.length=" + logSSC.length + " next=" + next);
1545            int i = next;
1546            if (logSSC[i] == null) {
1547                // logSSC is not full so back to the beginning
1548                i = 0;
1549            }
1550            do {
1551                log(logSSC[i].toString());
1552                if (++i >= logSSC.length) {
1553                    i = 0;
1554                }
1555            } while (i != next);
1556            log(prompt + ": ----------------");
1557        }
1558    }
1559
1560    boolean idMatch(int rSubId, int subId, int phoneId) {
1561        if(rSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
1562            if(subId < 0) {
1563                // Invalid case, we need compare phoneId with default one.
1564                return (mDefaultPhoneId == phoneId);
1565            }
1566            return (subId == mDefaultSubId);
1567        } else {
1568            return (rSubId == subId);
1569        }
1570    }
1571
1572    private void checkPossibleMissNotify(Record r, int phoneId) {
1573        int events = r.events;
1574
1575        if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
1576            try {
1577                if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" +
1578                        mServiceState[phoneId]);
1579                r.callback.onServiceStateChanged(
1580                        new ServiceState(mServiceState[phoneId]));
1581            } catch (RemoteException ex) {
1582                mRemoveList.add(r.binder);
1583            }
1584        }
1585
1586        if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
1587            try {
1588                SignalStrength signalStrength = mSignalStrength[phoneId];
1589                if (DBG) {
1590                    log("checkPossibleMissNotify: onSignalStrengthsChanged SS=" + signalStrength);
1591                }
1592                r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
1593            } catch (RemoteException ex) {
1594                mRemoveList.add(r.binder);
1595            }
1596        }
1597
1598        if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
1599            try {
1600                int gsmSignalStrength = mSignalStrength[phoneId]
1601                        .getGsmSignalStrength();
1602                if (DBG) {
1603                    log("checkPossibleMissNotify: onSignalStrengthChanged SS=" +
1604                            gsmSignalStrength);
1605                }
1606                r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
1607                        : gsmSignalStrength));
1608            } catch (RemoteException ex) {
1609                mRemoveList.add(r.binder);
1610            }
1611        }
1612
1613        if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
1614            try {
1615                if (DBG_LOC) {
1616                    log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
1617                            + mCellInfo.get(phoneId));
1618                }
1619                r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
1620            } catch (RemoteException ex) {
1621                mRemoveList.add(r.binder);
1622            }
1623        }
1624
1625        if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
1626            try {
1627                if (VDBG) {
1628                    log("checkPossibleMissNotify: onMessageWaitingIndicatorChanged phoneId="
1629                            + phoneId + " mwi=" + mMessageWaiting[phoneId]);
1630                }
1631                r.callback.onMessageWaitingIndicatorChanged(
1632                        mMessageWaiting[phoneId]);
1633            } catch (RemoteException ex) {
1634                mRemoveList.add(r.binder);
1635            }
1636        }
1637
1638        if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
1639            try {
1640                if (VDBG) {
1641                    log("checkPossibleMissNotify: onCallForwardingIndicatorChanged phoneId="
1642                        + phoneId + " cfi=" + mCallForwarding[phoneId]);
1643                }
1644                r.callback.onCallForwardingIndicatorChanged(
1645                        mCallForwarding[phoneId]);
1646            } catch (RemoteException ex) {
1647                mRemoveList.add(r.binder);
1648            }
1649        }
1650
1651        if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
1652            try {
1653                if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
1654                        + mCellLocation[phoneId]);
1655                r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
1656            } catch (RemoteException ex) {
1657                mRemoveList.add(r.binder);
1658            }
1659        }
1660
1661        if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
1662            try {
1663                if (DBG) {
1664                    log("checkPossibleMissNotify: onDataConnectionStateChanged(mDataConnectionState"
1665                            + "=" + mDataConnectionState[phoneId]
1666                            + ", mDataConnectionNetworkType=" + mDataConnectionNetworkType[phoneId]
1667                            + ")");
1668                }
1669                r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
1670                        mDataConnectionNetworkType[phoneId]);
1671            } catch (RemoteException ex) {
1672                mRemoveList.add(r.binder);
1673            }
1674        }
1675    }
1676}
1677