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