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