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