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