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