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