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