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