Home | History | Annotate | Download | only in server
      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 
     17 package com.android.server;
     18 
     19 import android.Manifest;
     20 import android.app.ActivityManager;
     21 import android.app.AppOpsManager;
     22 import android.content.BroadcastReceiver;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.IntentFilter;
     26 import android.content.pm.PackageManager;
     27 import android.net.LinkProperties;
     28 import android.net.NetworkCapabilities;
     29 import android.os.Binder;
     30 import android.os.Bundle;
     31 import android.os.Handler;
     32 import android.os.IBinder;
     33 import android.os.Message;
     34 import android.os.RemoteException;
     35 import android.os.UserHandle;
     36 import android.telephony.CellLocation;
     37 import android.telephony.Rlog;
     38 import android.telephony.TelephonyManager;
     39 import android.telephony.SubscriptionManager;
     40 import android.telephony.PhoneStateListener;
     41 import android.telephony.ServiceState;
     42 import android.telephony.SignalStrength;
     43 import android.telephony.CellInfo;
     44 import android.telephony.VoLteServiceState;
     45 import android.telephony.DisconnectCause;
     46 import android.telephony.PreciseCallState;
     47 import android.telephony.PreciseDataConnectionState;
     48 import android.telephony.PreciseDisconnectCause;
     49 import android.text.TextUtils;
     50 import android.text.format.Time;
     51 
     52 import java.util.ArrayList;
     53 import java.util.List;
     54 import java.io.FileDescriptor;
     55 import java.io.PrintWriter;
     56 
     57 import com.android.internal.app.IBatteryStats;
     58 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
     59 import com.android.internal.telephony.ITelephonyRegistry;
     60 import com.android.internal.telephony.IPhoneStateListener;
     61 import com.android.internal.telephony.DefaultPhoneNotifier;
     62 import com.android.internal.telephony.PhoneConstants;
     63 import com.android.internal.telephony.ServiceStateTracker;
     64 import com.android.internal.telephony.TelephonyIntents;
     65 import 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(int 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  */
     81 class 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 callingPackage;
     89 
     90         IBinder binder;
     91 
     92         IPhoneStateListener callback;
     93         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
     94 
     95         int callerUserId;
     96 
     97         int events;
     98 
     99         int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    100 
    101         int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
    102 
    103         boolean canReadPhoneState;
    104 
    105         boolean matchPhoneStateListenerEvent(int events) {
    106             return (callback != null) && ((events & this.events) != 0);
    107         }
    108 
    109         boolean matchOnSubscriptionsChangedListener() {
    110             return (onSubscriptionsChangedListenerCallback != null);
    111         }
    112 
    113         @Override
    114         public String toString() {
    115             return "{callingPackage=" + callingPackage + " binder=" + binder
    116                     + " callback=" + callback
    117                     + " onSubscriptionsChangedListenererCallback="
    118                                             + onSubscriptionsChangedListenerCallback
    119                     + " callerUserId=" + callerUserId + " subId=" + subId + " phoneId=" + phoneId
    120                     + " events=" + Integer.toHexString(events)
    121                     + " canReadPhoneState=" + canReadPhoneState + "}";
    122         }
    123     }
    124 
    125     private final Context mContext;
    126 
    127     // access should be inside synchronized (mRecords) for these two fields
    128     private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
    129     private final ArrayList<Record> mRecords = new ArrayList<Record>();
    130 
    131     private final IBatteryStats mBatteryStats;
    132 
    133     private final AppOpsManager mAppOps;
    134 
    135     private boolean hasNotifySubscriptionInfoChangedOccurred = false;
    136 
    137     private int mNumPhones;
    138 
    139     private int[] mCallState;
    140 
    141     private String[] mCallIncomingNumber;
    142 
    143     private ServiceState[] mServiceState;
    144 
    145     private SignalStrength[] mSignalStrength;
    146 
    147     private boolean[] mMessageWaiting;
    148 
    149     private boolean[] mCallForwarding;
    150 
    151     private int[] mDataActivity;
    152 
    153     private int[] mDataConnectionState;
    154 
    155     private boolean[] mDataConnectionPossible;
    156 
    157     private String[] mDataConnectionReason;
    158 
    159     private String[] mDataConnectionApn;
    160 
    161     private ArrayList<String> mConnectedApns;
    162 
    163     private LinkProperties[] mDataConnectionLinkProperties;
    164 
    165     private NetworkCapabilities[] mDataConnectionNetworkCapabilities;
    166 
    167     private Bundle[] mCellLocation;
    168 
    169     private int[] mDataConnectionNetworkType;
    170 
    171     private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
    172 
    173     private ArrayList<List<CellInfo>> mCellInfo = null;
    174 
    175     private VoLteServiceState mVoLteServiceState = new VoLteServiceState();
    176 
    177     private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    178 
    179     private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
    180 
    181     private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
    182 
    183     private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
    184 
    185     private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
    186 
    187     private PreciseCallState mPreciseCallState = new PreciseCallState();
    188 
    189     private boolean mCarrierNetworkChangeState = false;
    190 
    191     private PreciseDataConnectionState mPreciseDataConnectionState =
    192                 new PreciseDataConnectionState();
    193 
    194     static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
    195                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
    196                 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
    197                 PhoneStateListener.LISTEN_VOLTE_STATE;
    198 
    199     static final int CHECK_PHONE_STATE_PERMISSION_MASK =
    200                 PhoneStateListener.LISTEN_CALL_STATE |
    201                 PhoneStateListener.LISTEN_DATA_ACTIVITY |
    202                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
    203 
    204     static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
    205                 PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
    206                 PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
    207 
    208     private static final int MSG_USER_SWITCHED = 1;
    209     private static final int MSG_UPDATE_DEFAULT_SUB = 2;
    210 
    211     private final Handler mHandler = new Handler() {
    212         @Override
    213         public void handleMessage(Message msg) {
    214             switch (msg.what) {
    215                 case MSG_USER_SWITCHED: {
    216                     if (VDBG) log("MSG_USER_SWITCHED userId=" + msg.arg1);
    217                     int numPhones = TelephonyManager.getDefault().getPhoneCount();
    218                     for (int sub = 0; sub < numPhones; sub++) {
    219                         TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
    220                                 mCellLocation[sub]);
    221                     }
    222                     break;
    223                 }
    224                 case MSG_UPDATE_DEFAULT_SUB: {
    225                     int newDefaultPhoneId = msg.arg1;
    226                     int newDefaultSubId = (Integer)(msg.obj);
    227                     if (VDBG) {
    228                         log("MSG_UPDATE_DEFAULT_SUB:current mDefaultSubId=" + mDefaultSubId
    229                             + " current mDefaultPhoneId=" + mDefaultPhoneId + " newDefaultSubId= "
    230                             + newDefaultSubId + " newDefaultPhoneId=" + newDefaultPhoneId);
    231                     }
    232 
    233                     //Due to possible risk condition,(notify call back using the new
    234                     //defaultSubId comes before new defaultSubId update) we need to recall all
    235                     //possible missed notify callback
    236                     synchronized (mRecords) {
    237                         for (Record r : mRecords) {
    238                             if(r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
    239                                 checkPossibleMissNotify(r, newDefaultPhoneId);
    240                             }
    241                         }
    242                         handleRemoveListLocked();
    243                     }
    244                     mDefaultSubId = newDefaultSubId;
    245                     mDefaultPhoneId = newDefaultPhoneId;
    246                 }
    247             }
    248         }
    249     };
    250 
    251     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    252         @Override
    253         public void onReceive(Context context, Intent intent) {
    254             String action = intent.getAction();
    255             if (VDBG) log("mBroadcastReceiver: action=" + action);
    256             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
    257                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
    258                 if (DBG) log("onReceive: userHandle=" + userHandle);
    259                 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, userHandle, 0));
    260             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED)) {
    261                 Integer newDefaultSubIdObj = new Integer(intent.getIntExtra(
    262                         PhoneConstants.SUBSCRIPTION_KEY,
    263                         SubscriptionManager.getDefaultSubscriptionId()));
    264                 int newDefaultPhoneId = intent.getIntExtra(PhoneConstants.SLOT_KEY,
    265                     SubscriptionManager.getPhoneId(mDefaultSubId));
    266                 if (DBG) {
    267                     log("onReceive:current mDefaultSubId=" + mDefaultSubId
    268                         + " current mDefaultPhoneId=" + mDefaultPhoneId + " newDefaultSubId= "
    269                         + newDefaultSubIdObj + " newDefaultPhoneId=" + newDefaultPhoneId);
    270                 }
    271 
    272                 if(validatePhoneId(newDefaultPhoneId) && (!newDefaultSubIdObj.equals(mDefaultSubId)
    273                         || (newDefaultPhoneId != mDefaultPhoneId))) {
    274                     mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_DEFAULT_SUB,
    275                             newDefaultPhoneId, 0, newDefaultSubIdObj));
    276                 }
    277             }
    278         }
    279     };
    280 
    281     // we keep a copy of all of the state so we can send it out when folks
    282     // register for it
    283     //
    284     // In these calls we call with the lock held. This is safe becasuse remote
    285     // calls go through a oneway interface and local calls going through a
    286     // handler before they get to app code.
    287 
    288     TelephonyRegistry(Context context) {
    289         CellLocation  location = CellLocation.getEmpty();
    290 
    291         mContext = context;
    292         mBatteryStats = BatteryStatsService.getService();
    293         mConnectedApns = new ArrayList<String>();
    294 
    295         int numPhones = TelephonyManager.getDefault().getPhoneCount();
    296         if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones);
    297         mNumPhones = numPhones;
    298         mCallState = new int[numPhones];
    299         mDataActivity = new int[numPhones];
    300         mDataConnectionState = new int[numPhones];
    301         mDataConnectionNetworkType = new int[numPhones];
    302         mCallIncomingNumber = new String[numPhones];
    303         mServiceState = new ServiceState[numPhones];
    304         mSignalStrength = new SignalStrength[numPhones];
    305         mMessageWaiting = new boolean[numPhones];
    306         mDataConnectionPossible = new boolean[numPhones];
    307         mDataConnectionReason = new String[numPhones];
    308         mDataConnectionApn = new String[numPhones];
    309         mCallForwarding = new boolean[numPhones];
    310         mCellLocation = new Bundle[numPhones];
    311         mDataConnectionLinkProperties = new LinkProperties[numPhones];
    312         mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
    313         mCellInfo = new ArrayList<List<CellInfo>>();
    314         for (int i = 0; i < numPhones; i++) {
    315             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
    316             mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
    317             mDataConnectionState[i] = TelephonyManager.DATA_UNKNOWN;
    318             mCallIncomingNumber[i] =  "";
    319             mServiceState[i] =  new ServiceState();
    320             mSignalStrength[i] =  new SignalStrength();
    321             mMessageWaiting[i] =  false;
    322             mCallForwarding[i] =  false;
    323             mDataConnectionPossible[i] = false;
    324             mDataConnectionReason[i] =  "";
    325             mDataConnectionApn[i] =  "";
    326             mCellLocation[i] = new Bundle();
    327             mCellInfo.add(i, null);
    328         }
    329 
    330         // Note that location can be null for non-phone builds like
    331         // like the generic one.
    332         if (location != null) {
    333             for (int i = 0; i < numPhones; i++) {
    334                 location.fillInNotifierBundle(mCellLocation[i]);
    335             }
    336         }
    337         mConnectedApns = new ArrayList<String>();
    338 
    339         mAppOps = mContext.getSystemService(AppOpsManager.class);
    340     }
    341 
    342     public void systemRunning() {
    343         // Watch for interesting updates
    344         final IntentFilter filter = new IntentFilter();
    345         filter.addAction(Intent.ACTION_USER_SWITCHED);
    346         filter.addAction(Intent.ACTION_USER_REMOVED);
    347         filter.addAction(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
    348         log("systemRunning register for intents");
    349         mContext.registerReceiver(mBroadcastReceiver, filter);
    350     }
    351 
    352     @Override
    353     public void addOnSubscriptionsChangedListener(String callingPackage,
    354             IOnSubscriptionsChangedListener callback) {
    355         int callerUserId = UserHandle.getCallingUserId();
    356         if (VDBG) {
    357             log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
    358                 + " callerUserId="  + callerUserId + " callback=" + callback
    359                 + " callback.asBinder=" + callback.asBinder());
    360         }
    361 
    362         try {
    363             mContext.enforceCallingOrSelfPermission(
    364                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
    365                     "addOnSubscriptionsChangedListener");
    366             // SKIP checking for run-time permission since caller or self has PRIVILEGED permission
    367         } catch (SecurityException e) {
    368             mContext.enforceCallingOrSelfPermission(
    369                     android.Manifest.permission.READ_PHONE_STATE,
    370                     "addOnSubscriptionsChangedListener");
    371 
    372             if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
    373                     callingPackage) != AppOpsManager.MODE_ALLOWED) {
    374                 return;
    375             }
    376         }
    377 
    378         Record r;
    379 
    380         synchronized (mRecords) {
    381             // register
    382             find_and_add: {
    383                 IBinder b = callback.asBinder();
    384                 final int N = mRecords.size();
    385                 for (int i = 0; i < N; i++) {
    386                     r = mRecords.get(i);
    387                     if (b == r.binder) {
    388                         break find_and_add;
    389                     }
    390                 }
    391                 r = new Record();
    392                 r.binder = b;
    393                 mRecords.add(r);
    394                 if (DBG) log("listen oscl: add new record");
    395             }
    396 
    397             r.onSubscriptionsChangedListenerCallback = callback;
    398             r.callingPackage = callingPackage;
    399             r.callerUserId = callerUserId;
    400             r.events = 0;
    401             r.canReadPhoneState = true; // permission has been enforced above
    402             if (DBG) {
    403                 log("listen oscl:  Register r=" + r);
    404             }
    405             // Always notify when registration occurs if there has been a notification.
    406             if (hasNotifySubscriptionInfoChangedOccurred) {
    407                 try {
    408                     if (VDBG) log("listen oscl: send to r=" + r);
    409                     r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
    410                     if (VDBG) log("listen oscl: sent to r=" + r);
    411                 } catch (RemoteException e) {
    412                     if (VDBG) log("listen oscl: remote exception sending to r=" + r + " e=" + e);
    413                     remove(r.binder);
    414                 }
    415             } else {
    416                 log("listen oscl: hasNotifySubscriptionInfoChangedOccurred==false no callback");
    417             }
    418         }
    419     }
    420 
    421     @Override
    422     public void removeOnSubscriptionsChangedListener(String pkgForDebug,
    423             IOnSubscriptionsChangedListener callback) {
    424         if (DBG) log("listen oscl: Unregister");
    425         remove(callback.asBinder());
    426     }
    427 
    428     @Override
    429     public void notifySubscriptionInfoChanged() {
    430         if (VDBG) log("notifySubscriptionInfoChanged:");
    431         synchronized (mRecords) {
    432             if (!hasNotifySubscriptionInfoChangedOccurred) {
    433                 log("notifySubscriptionInfoChanged: first invocation mRecords.size="
    434                         + mRecords.size());
    435             }
    436             hasNotifySubscriptionInfoChangedOccurred = true;
    437             mRemoveList.clear();
    438             for (Record r : mRecords) {
    439                 if (r.matchOnSubscriptionsChangedListener()) {
    440                     try {
    441                         if (VDBG) log("notifySubscriptionInfoChanged: call osc to r=" + r);
    442                         r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
    443                         if (VDBG) log("notifySubscriptionInfoChanged: done osc to r=" + r);
    444                     } catch (RemoteException ex) {
    445                         if (VDBG) log("notifySubscriptionInfoChanged: RemoteException r=" + r);
    446                         mRemoveList.add(r.binder);
    447                     }
    448                 }
    449             }
    450             handleRemoveListLocked();
    451         }
    452     }
    453 
    454     @Override
    455     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
    456             boolean notifyNow) {
    457         listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
    458                 events, notifyNow);
    459     }
    460 
    461     @Override
    462     public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback,
    463             int events, boolean notifyNow) {
    464         listen(pkgForDebug, callback, events, notifyNow, subId);
    465     }
    466 
    467     private void listen(String callingPackage, IPhoneStateListener callback, int events,
    468             boolean notifyNow, int subId) {
    469         int callerUserId = UserHandle.getCallingUserId();
    470         if (VDBG) {
    471             log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
    472                 + " notifyNow=" + notifyNow + " subId=" + subId + " myUserId="
    473                 + UserHandle.myUserId() + " callerUserId=" + callerUserId);
    474         }
    475 
    476         if (events != PhoneStateListener.LISTEN_NONE) {
    477             /* Checks permission and throws Security exception */
    478             checkListenerPermission(events);
    479 
    480             if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
    481                 try {
    482                     mContext.enforceCallingOrSelfPermission(
    483                             android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
    484                     // SKIP checking for run-time permission since caller or self has PRIVILEGED
    485                     // permission
    486                 } catch (SecurityException e) {
    487                     if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
    488                             callingPackage) != AppOpsManager.MODE_ALLOWED) {
    489                         return;
    490                     }
    491                 }
    492             }
    493 
    494             synchronized (mRecords) {
    495                 // register
    496                 Record r;
    497                 find_and_add: {
    498                     IBinder b = callback.asBinder();
    499                     final int N = mRecords.size();
    500                     for (int i = 0; i < N; i++) {
    501                         r = mRecords.get(i);
    502                         if (b == r.binder) {
    503                             break find_and_add;
    504                         }
    505                     }
    506                     r = new Record();
    507                     r.binder = b;
    508                     mRecords.add(r);
    509                     if (DBG) log("listen: add new record");
    510                 }
    511 
    512                 r.callback = callback;
    513                 r.callingPackage = callingPackage;
    514                 r.callerUserId = callerUserId;
    515                 boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK
    516                         | ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0;
    517                 r.canReadPhoneState = isPhoneStateEvent && canReadPhoneState(callingPackage);
    518                 // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
    519                 // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
    520                 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
    521                     r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
    522                  } else {//APP specify subID
    523                     r.subId = subId;
    524                 }
    525                 r.phoneId = SubscriptionManager.getPhoneId(r.subId);
    526 
    527                 int phoneId = r.phoneId;
    528                 r.events = events;
    529                 if (DBG) {
    530                     log("listen:  Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
    531                 }
    532                 if (VDBG) toStringLogSSC("listen");
    533                 if (notifyNow && validatePhoneId(phoneId)) {
    534                     if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
    535                         try {
    536                             if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
    537                             r.callback.onServiceStateChanged(
    538                                     new ServiceState(mServiceState[phoneId]));
    539                         } catch (RemoteException ex) {
    540                             remove(r.binder);
    541                         }
    542                     }
    543                     if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
    544                         try {
    545                             int gsmSignalStrength = mSignalStrength[phoneId]
    546                                     .getGsmSignalStrength();
    547                             r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
    548                                     : gsmSignalStrength));
    549                         } catch (RemoteException ex) {
    550                             remove(r.binder);
    551                         }
    552                     }
    553                     if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
    554                         try {
    555                             r.callback.onMessageWaitingIndicatorChanged(
    556                                     mMessageWaiting[phoneId]);
    557                         } catch (RemoteException ex) {
    558                             remove(r.binder);
    559                         }
    560                     }
    561                     if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
    562                         try {
    563                             r.callback.onCallForwardingIndicatorChanged(
    564                                     mCallForwarding[phoneId]);
    565                         } catch (RemoteException ex) {
    566                             remove(r.binder);
    567                         }
    568                     }
    569                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
    570                         try {
    571                             if (DBG_LOC) log("listen: mCellLocation = "
    572                                     + mCellLocation[phoneId]);
    573                             r.callback.onCellLocationChanged(
    574                                     new Bundle(mCellLocation[phoneId]));
    575                         } catch (RemoteException ex) {
    576                             remove(r.binder);
    577                         }
    578                     }
    579                     if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
    580                         try {
    581                             r.callback.onCallStateChanged(mCallState[phoneId],
    582                                      getCallIncomingNumber(r, phoneId));
    583                         } catch (RemoteException ex) {
    584                             remove(r.binder);
    585                         }
    586                     }
    587                     if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
    588                         try {
    589                             r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
    590                                 mDataConnectionNetworkType[phoneId]);
    591                         } catch (RemoteException ex) {
    592                             remove(r.binder);
    593                         }
    594                     }
    595                     if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
    596                         try {
    597                             r.callback.onDataActivity(mDataActivity[phoneId]);
    598                         } catch (RemoteException ex) {
    599                             remove(r.binder);
    600                         }
    601                     }
    602                     if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
    603                         try {
    604                             r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
    605                         } catch (RemoteException ex) {
    606                             remove(r.binder);
    607                         }
    608                     }
    609                     if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
    610                         try {
    611                             r.callback.onOtaspChanged(mOtaspMode);
    612                         } catch (RemoteException ex) {
    613                             remove(r.binder);
    614                         }
    615                     }
    616                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
    617                         try {
    618                             if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
    619                                     + mCellInfo.get(phoneId));
    620                             r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
    621                         } catch (RemoteException ex) {
    622                             remove(r.binder);
    623                         }
    624                     }
    625                     if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
    626                         try {
    627                             r.callback.onPreciseCallStateChanged(mPreciseCallState);
    628                         } catch (RemoteException ex) {
    629                             remove(r.binder);
    630                         }
    631                     }
    632                     if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
    633                         try {
    634                             r.callback.onPreciseDataConnectionStateChanged(
    635                                     mPreciseDataConnectionState);
    636                         } catch (RemoteException ex) {
    637                             remove(r.binder);
    638                         }
    639                     }
    640                     if ((events & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) {
    641                         try {
    642                             r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState);
    643                         } catch (RemoteException ex) {
    644                             remove(r.binder);
    645                         }
    646                     }
    647                 }
    648             }
    649         } else {
    650             if(DBG) log("listen: Unregister");
    651             remove(callback.asBinder());
    652         }
    653     }
    654 
    655     private boolean canReadPhoneState(String callingPackage) {
    656         if (mContext.checkCallingOrSelfPermission(
    657                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) ==
    658                 PackageManager.PERMISSION_GRANTED) {
    659             // SKIP checking for run-time permission since caller or self has PRIVILEGED permission
    660             return true;
    661         }
    662         boolean canReadPhoneState = mContext.checkCallingOrSelfPermission(
    663                 android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED;
    664         if (canReadPhoneState &&
    665                 mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
    666                         callingPackage) != AppOpsManager.MODE_ALLOWED) {
    667             return false;
    668         }
    669         return canReadPhoneState;
    670     }
    671 
    672     private String getCallIncomingNumber(Record record, int phoneId) {
    673         // Hide the number if record's process has no READ_PHONE_STATE permission
    674         return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : "";
    675     }
    676 
    677     private void remove(IBinder binder) {
    678         synchronized (mRecords) {
    679             final int recordCount = mRecords.size();
    680             for (int i = 0; i < recordCount; i++) {
    681                 if (mRecords.get(i).binder == binder) {
    682                     if (DBG) {
    683                         Record r = mRecords.get(i);
    684                         log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage
    685                                 + "r.callback" + r.callback);
    686                     }
    687                     mRecords.remove(i);
    688                     return;
    689                 }
    690             }
    691         }
    692     }
    693 
    694     public void notifyCallState(int state, String incomingNumber) {
    695         if (!checkNotifyPermission("notifyCallState()")) {
    696             return;
    697         }
    698 
    699         if (VDBG) {
    700             log("notifyCallState: state=" + state + " incomingNumber=" + incomingNumber);
    701         }
    702 
    703         synchronized (mRecords) {
    704             for (Record r : mRecords) {
    705                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
    706                         (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
    707                     try {
    708                         String incomingNumberOrEmpty = r.canReadPhoneState ? incomingNumber : "";
    709                         r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
    710                     } catch (RemoteException ex) {
    711                         mRemoveList.add(r.binder);
    712                     }
    713                 }
    714             }
    715             handleRemoveListLocked();
    716         }
    717 
    718         // Called only by Telecomm to communicate call state across different phone accounts. So
    719         // there is no need to add a valid subId or slotId.
    720         broadcastCallStateChanged(state, incomingNumber,
    721                 SubscriptionManager.INVALID_PHONE_INDEX,
    722                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
    723     }
    724 
    725     public void notifyCallStateForPhoneId(int phoneId, int subId, int state,
    726                 String incomingNumber) {
    727         if (!checkNotifyPermission("notifyCallState()")) {
    728             return;
    729         }
    730         if (VDBG) {
    731             log("notifyCallStateForPhoneId: subId=" + subId
    732                 + " state=" + state + " incomingNumber=" + incomingNumber);
    733         }
    734         synchronized (mRecords) {
    735             if (validatePhoneId(phoneId)) {
    736                 mCallState[phoneId] = state;
    737                 mCallIncomingNumber[phoneId] = incomingNumber;
    738                 for (Record r : mRecords) {
    739                     if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
    740                             (r.subId == subId) &&
    741                             (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
    742                         try {
    743                             String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId);
    744                             r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
    745                         } catch (RemoteException ex) {
    746                             mRemoveList.add(r.binder);
    747                         }
    748                     }
    749                 }
    750             }
    751             handleRemoveListLocked();
    752         }
    753         broadcastCallStateChanged(state, incomingNumber, phoneId, subId);
    754     }
    755 
    756     public void notifyServiceStateForPhoneId(int phoneId, int subId, ServiceState state) {
    757         if (!checkNotifyPermission("notifyServiceState()")){
    758             return;
    759         }
    760 
    761         synchronized (mRecords) {
    762             if (VDBG) {
    763                 log("notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
    764                     + " state=" + state);
    765             }
    766             if (validatePhoneId(phoneId)) {
    767                 mServiceState[phoneId] = state;
    768                 logServiceStateChanged("notifyServiceStateForSubscriber", subId, phoneId, state);
    769                 if (VDBG) toStringLogSSC("notifyServiceStateForSubscriber");
    770 
    771                 for (Record r : mRecords) {
    772                     if (VDBG) {
    773                         log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
    774                                 + " phoneId=" + phoneId + " state=" + state);
    775                     }
    776                     if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SERVICE_STATE) &&
    777                             idMatch(r.subId, subId, phoneId)) {
    778                         try {
    779                             if (DBG) {
    780                                 log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
    781                                         + " subId=" + subId + " phoneId=" + phoneId
    782                                         + " state=" + state);
    783                             }
    784                             r.callback.onServiceStateChanged(new ServiceState(state));
    785                         } catch (RemoteException ex) {
    786                             mRemoveList.add(r.binder);
    787                         }
    788                     }
    789                 }
    790             } else {
    791                 log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId);
    792             }
    793             handleRemoveListLocked();
    794         }
    795         broadcastServiceStateChanged(state, phoneId, subId);
    796     }
    797 
    798     public void notifySignalStrengthForPhoneId(int phoneId, int subId,
    799                 SignalStrength signalStrength) {
    800         if (!checkNotifyPermission("notifySignalStrength()")) {
    801             return;
    802         }
    803         if (VDBG) {
    804             log("notifySignalStrengthForPhoneId: subId=" + subId
    805                 +" phoneId=" + phoneId + " signalStrength=" + signalStrength);
    806             toStringLogSSC("notifySignalStrengthForPhoneId");
    807         }
    808 
    809         synchronized (mRecords) {
    810             if (validatePhoneId(phoneId)) {
    811                 if (VDBG) log("notifySignalStrengthForPhoneId: valid phoneId=" + phoneId);
    812                 mSignalStrength[phoneId] = signalStrength;
    813                 for (Record r : mRecords) {
    814                     if (VDBG) {
    815                         log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId
    816                                 + " phoneId=" + phoneId + " ss=" + signalStrength);
    817                     }
    818                     if (r.matchPhoneStateListenerEvent(
    819                                 PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) &&
    820                             idMatch(r.subId, subId, phoneId)) {
    821                         try {
    822                             if (DBG) {
    823                                 log("notifySignalStrengthForPhoneId: callback.onSsS r=" + r
    824                                         + " subId=" + subId + " phoneId=" + phoneId
    825                                         + " ss=" + signalStrength);
    826                             }
    827                             r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
    828                         } catch (RemoteException ex) {
    829                             mRemoveList.add(r.binder);
    830                         }
    831                     }
    832                     if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) &&
    833                             idMatch(r.subId, subId, phoneId)){
    834                         try {
    835                             int gsmSignalStrength = signalStrength.getGsmSignalStrength();
    836                             int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
    837                             if (DBG) {
    838                                 log("notifySignalStrengthForPhoneId: callback.onSS r=" + r
    839                                         + " subId=" + subId + " phoneId=" + phoneId
    840                                         + " gsmSS=" + gsmSignalStrength + " ss=" + ss);
    841                             }
    842                             r.callback.onSignalStrengthChanged(ss);
    843                         } catch (RemoteException ex) {
    844                             mRemoveList.add(r.binder);
    845                         }
    846                     }
    847                 }
    848             } else {
    849                 log("notifySignalStrengthForPhoneId: invalid phoneId=" + phoneId);
    850             }
    851             handleRemoveListLocked();
    852         }
    853         broadcastSignalStrengthChanged(signalStrength, phoneId, subId);
    854     }
    855 
    856     @Override
    857     public void notifyCarrierNetworkChange(boolean active) {
    858         enforceNotifyPermissionOrCarrierPrivilege("notifyCarrierNetworkChange()");
    859 
    860         if (VDBG) {
    861             log("notifyCarrierNetworkChange: active=" + active);
    862         }
    863 
    864         synchronized (mRecords) {
    865             mCarrierNetworkChangeState = active;
    866             for (Record r : mRecords) {
    867                 if (r.matchPhoneStateListenerEvent(
    868                         PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE)) {
    869                     try {
    870                         r.callback.onCarrierNetworkChange(active);
    871                     } catch (RemoteException ex) {
    872                         mRemoveList.add(r.binder);
    873                     }
    874                 }
    875             }
    876             handleRemoveListLocked();
    877         }
    878     }
    879 
    880     public void notifyCellInfo(List<CellInfo> cellInfo) {
    881          notifyCellInfoForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellInfo);
    882     }
    883 
    884     public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) {
    885         if (!checkNotifyPermission("notifyCellInfo()")) {
    886             return;
    887         }
    888         if (VDBG) {
    889             log("notifyCellInfoForSubscriber: subId=" + subId
    890                 + " cellInfo=" + cellInfo);
    891         }
    892 
    893         synchronized (mRecords) {
    894             int phoneId = SubscriptionManager.getPhoneId(subId);
    895             if (validatePhoneId(phoneId)) {
    896                 mCellInfo.set(phoneId, cellInfo);
    897                 for (Record r : mRecords) {
    898                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
    899                             idMatch(r.subId, subId, phoneId)) {
    900                         try {
    901                             if (DBG_LOC) {
    902                                 log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
    903                             }
    904                             r.callback.onCellInfoChanged(cellInfo);
    905                         } catch (RemoteException ex) {
    906                             mRemoveList.add(r.binder);
    907                         }
    908                     }
    909                 }
    910             }
    911             handleRemoveListLocked();
    912         }
    913     }
    914 
    915     @Override
    916     public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
    917         if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
    918             return;
    919         }
    920         if (VDBG) {
    921             log("notifyMessageWaitingChangedForSubscriberPhoneID: subId=" + phoneId
    922                 + " mwi=" + mwi);
    923         }
    924         synchronized (mRecords) {
    925             if (validatePhoneId(phoneId)) {
    926                 mMessageWaiting[phoneId] = mwi;
    927                 for (Record r : mRecords) {
    928                     if (r.matchPhoneStateListenerEvent(
    929                             PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) &&
    930                             idMatch(r.subId, subId, phoneId)) {
    931                         try {
    932                             r.callback.onMessageWaitingIndicatorChanged(mwi);
    933                         } catch (RemoteException ex) {
    934                             mRemoveList.add(r.binder);
    935                         }
    936                     }
    937                 }
    938             }
    939             handleRemoveListLocked();
    940         }
    941     }
    942 
    943     public void notifyCallForwardingChanged(boolean cfi) {
    944         notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cfi);
    945     }
    946 
    947     public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) {
    948         if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
    949             return;
    950         }
    951         if (VDBG) {
    952             log("notifyCallForwardingChangedForSubscriber: subId=" + subId
    953                 + " cfi=" + cfi);
    954         }
    955         synchronized (mRecords) {
    956             int phoneId = SubscriptionManager.getPhoneId(subId);
    957             if (validatePhoneId(phoneId)) {
    958                 mCallForwarding[phoneId] = cfi;
    959                 for (Record r : mRecords) {
    960                     if (r.matchPhoneStateListenerEvent(
    961                             PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) &&
    962                             idMatch(r.subId, subId, phoneId)) {
    963                         try {
    964                             r.callback.onCallForwardingIndicatorChanged(cfi);
    965                         } catch (RemoteException ex) {
    966                             mRemoveList.add(r.binder);
    967                         }
    968                     }
    969                 }
    970             }
    971             handleRemoveListLocked();
    972         }
    973     }
    974 
    975     public void notifyDataActivity(int state) {
    976         notifyDataActivityForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state);
    977     }
    978 
    979     public void notifyDataActivityForSubscriber(int subId, int state) {
    980         if (!checkNotifyPermission("notifyDataActivity()" )) {
    981             return;
    982         }
    983         synchronized (mRecords) {
    984             int phoneId = SubscriptionManager.getPhoneId(subId);
    985             if (validatePhoneId(phoneId)) {
    986                 mDataActivity[phoneId] = state;
    987                 for (Record r : mRecords) {
    988                     if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY)) {
    989                         try {
    990                             r.callback.onDataActivity(state);
    991                         } catch (RemoteException ex) {
    992                             mRemoveList.add(r.binder);
    993                         }
    994                     }
    995                 }
    996             }
    997             handleRemoveListLocked();
    998         }
    999     }
   1000 
   1001     public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
   1002             String reason, String apn, String apnType, LinkProperties linkProperties,
   1003             NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
   1004         notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state,
   1005             isDataConnectivityPossible,reason, apn, apnType, linkProperties,
   1006             networkCapabilities, networkType, roaming);
   1007     }
   1008 
   1009     public void notifyDataConnectionForSubscriber(int subId, int state,
   1010             boolean isDataConnectivityPossible, String reason, String apn, String apnType,
   1011             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
   1012             int networkType, boolean roaming) {
   1013         if (!checkNotifyPermission("notifyDataConnection()" )) {
   1014             return;
   1015         }
   1016         if (VDBG) {
   1017             log("notifyDataConnectionForSubscriber: subId=" + subId
   1018                 + " state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible
   1019                 + " reason='" + reason
   1020                 + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
   1021                 + " mRecords.size()=" + mRecords.size());
   1022         }
   1023         synchronized (mRecords) {
   1024             int phoneId = SubscriptionManager.getPhoneId(subId);
   1025             if (validatePhoneId(phoneId)) {
   1026                 boolean modified = false;
   1027                 if (state == TelephonyManager.DATA_CONNECTED) {
   1028                     if (!mConnectedApns.contains(apnType)) {
   1029                         mConnectedApns.add(apnType);
   1030                         if (mDataConnectionState[phoneId] != state) {
   1031                             mDataConnectionState[phoneId] = state;
   1032                             modified = true;
   1033                         }
   1034                     }
   1035                 } else {
   1036                     if (mConnectedApns.remove(apnType)) {
   1037                         if (mConnectedApns.isEmpty()) {
   1038                             mDataConnectionState[phoneId] = state;
   1039                             modified = true;
   1040                         } else {
   1041                             // leave mDataConnectionState as is and
   1042                             // send out the new status for the APN in question.
   1043                         }
   1044                     }
   1045                 }
   1046                 mDataConnectionPossible[phoneId] = isDataConnectivityPossible;
   1047                 mDataConnectionReason[phoneId] = reason;
   1048                 mDataConnectionLinkProperties[phoneId] = linkProperties;
   1049                 mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
   1050                 if (mDataConnectionNetworkType[phoneId] != networkType) {
   1051                     mDataConnectionNetworkType[phoneId] = networkType;
   1052                     // need to tell registered listeners about the new network type
   1053                     modified = true;
   1054                 }
   1055                 if (modified) {
   1056                     if (DBG) {
   1057                         log("onDataConnectionStateChanged(" + mDataConnectionState[phoneId]
   1058                             + ", " + mDataConnectionNetworkType[phoneId] + ")");
   1059                     }
   1060                     for (Record r : mRecords) {
   1061                         if (r.matchPhoneStateListenerEvent(
   1062                                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) &&
   1063                                 idMatch(r.subId, subId, phoneId)) {
   1064                             try {
   1065                                 log("Notify data connection state changed on sub: " +
   1066                                         subId);
   1067                                 r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
   1068                                         mDataConnectionNetworkType[phoneId]);
   1069                             } catch (RemoteException ex) {
   1070                                 mRemoveList.add(r.binder);
   1071                             }
   1072                         }
   1073                     }
   1074                     handleRemoveListLocked();
   1075                 }
   1076                 mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
   1077                         apnType, apn, reason, linkProperties, "");
   1078                 for (Record r : mRecords) {
   1079                     if (r.matchPhoneStateListenerEvent(
   1080                             PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
   1081                         try {
   1082                             r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
   1083                         } catch (RemoteException ex) {
   1084                             mRemoveList.add(r.binder);
   1085                         }
   1086                     }
   1087                 }
   1088             }
   1089             handleRemoveListLocked();
   1090         }
   1091         broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
   1092                 apnType, linkProperties, networkCapabilities, roaming, subId);
   1093         broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
   1094                 linkProperties, "");
   1095     }
   1096 
   1097     public void notifyDataConnectionFailed(String reason, String apnType) {
   1098          notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
   1099                  reason, apnType);
   1100     }
   1101 
   1102     public void notifyDataConnectionFailedForSubscriber(int subId,
   1103             String reason, String apnType) {
   1104         if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
   1105             return;
   1106         }
   1107         if (VDBG) {
   1108             log("notifyDataConnectionFailedForSubscriber: subId=" + subId
   1109                 + " reason=" + reason + " apnType=" + apnType);
   1110         }
   1111         synchronized (mRecords) {
   1112             mPreciseDataConnectionState = new PreciseDataConnectionState(
   1113                     TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
   1114                     apnType, "", reason, null, "");
   1115             for (Record r : mRecords) {
   1116                 if (r.matchPhoneStateListenerEvent(
   1117                         PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
   1118                     try {
   1119                         r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
   1120                     } catch (RemoteException ex) {
   1121                         mRemoveList.add(r.binder);
   1122                     }
   1123                 }
   1124             }
   1125             handleRemoveListLocked();
   1126         }
   1127         broadcastDataConnectionFailed(reason, apnType, subId);
   1128         broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
   1129                 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
   1130     }
   1131 
   1132     public void notifyCellLocation(Bundle cellLocation) {
   1133          notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
   1134     }
   1135 
   1136     public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
   1137         log("notifyCellLocationForSubscriber: subId=" + subId
   1138                 + " cellLocation=" + cellLocation);
   1139         if (!checkNotifyPermission("notifyCellLocation()")) {
   1140             return;
   1141         }
   1142         if (VDBG) {
   1143             log("notifyCellLocationForSubscriber: subId=" + subId
   1144                 + " cellLocation=" + cellLocation);
   1145         }
   1146         synchronized (mRecords) {
   1147             int phoneId = SubscriptionManager.getPhoneId(subId);
   1148             if (validatePhoneId(phoneId)) {
   1149                 mCellLocation[phoneId] = cellLocation;
   1150                 for (Record r : mRecords) {
   1151                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
   1152                             idMatch(r.subId, subId, phoneId)) {
   1153                         try {
   1154                             if (DBG_LOC) {
   1155                                 log("notifyCellLocation: cellLocation=" + cellLocation
   1156                                         + " r=" + r);
   1157                             }
   1158                             r.callback.onCellLocationChanged(new Bundle(cellLocation));
   1159                         } catch (RemoteException ex) {
   1160                             mRemoveList.add(r.binder);
   1161                         }
   1162                     }
   1163                 }
   1164             }
   1165             handleRemoveListLocked();
   1166         }
   1167     }
   1168 
   1169     public void notifyOtaspChanged(int otaspMode) {
   1170         if (!checkNotifyPermission("notifyOtaspChanged()" )) {
   1171             return;
   1172         }
   1173         synchronized (mRecords) {
   1174             mOtaspMode = otaspMode;
   1175             for (Record r : mRecords) {
   1176                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_OTASP_CHANGED)) {
   1177                     try {
   1178                         r.callback.onOtaspChanged(otaspMode);
   1179                     } catch (RemoteException ex) {
   1180                         mRemoveList.add(r.binder);
   1181                     }
   1182                 }
   1183             }
   1184             handleRemoveListLocked();
   1185         }
   1186     }
   1187 
   1188     public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
   1189             int backgroundCallState) {
   1190         if (!checkNotifyPermission("notifyPreciseCallState()")) {
   1191             return;
   1192         }
   1193         synchronized (mRecords) {
   1194             mRingingCallState = ringingCallState;
   1195             mForegroundCallState = foregroundCallState;
   1196             mBackgroundCallState = backgroundCallState;
   1197             mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
   1198                     backgroundCallState,
   1199                     DisconnectCause.NOT_VALID,
   1200                     PreciseDisconnectCause.NOT_VALID);
   1201             for (Record r : mRecords) {
   1202                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) {
   1203                     try {
   1204                         r.callback.onPreciseCallStateChanged(mPreciseCallState);
   1205                     } catch (RemoteException ex) {
   1206                         mRemoveList.add(r.binder);
   1207                     }
   1208                 }
   1209             }
   1210             handleRemoveListLocked();
   1211         }
   1212         broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
   1213                 DisconnectCause.NOT_VALID,
   1214                 PreciseDisconnectCause.NOT_VALID);
   1215     }
   1216 
   1217     public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
   1218         if (!checkNotifyPermission("notifyDisconnectCause()")) {
   1219             return;
   1220         }
   1221         synchronized (mRecords) {
   1222             mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
   1223                     mBackgroundCallState, disconnectCause, preciseDisconnectCause);
   1224             for (Record r : mRecords) {
   1225                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) {
   1226                     try {
   1227                         r.callback.onPreciseCallStateChanged(mPreciseCallState);
   1228                     } catch (RemoteException ex) {
   1229                         mRemoveList.add(r.binder);
   1230                     }
   1231                 }
   1232             }
   1233             handleRemoveListLocked();
   1234         }
   1235         broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
   1236                 mBackgroundCallState, disconnectCause, preciseDisconnectCause);
   1237     }
   1238 
   1239     public void notifyPreciseDataConnectionFailed(String reason, String apnType,
   1240             String apn, String failCause) {
   1241         if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
   1242             return;
   1243         }
   1244         synchronized (mRecords) {
   1245             mPreciseDataConnectionState = new PreciseDataConnectionState(
   1246                     TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
   1247                     apnType, apn, reason, null, failCause);
   1248             for (Record r : mRecords) {
   1249                 if (r.matchPhoneStateListenerEvent(
   1250                         PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)) {
   1251                     try {
   1252                         r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
   1253                     } catch (RemoteException ex) {
   1254                         mRemoveList.add(r.binder);
   1255                     }
   1256                 }
   1257             }
   1258             handleRemoveListLocked();
   1259         }
   1260         broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
   1261                 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
   1262     }
   1263 
   1264     public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
   1265         if (!checkNotifyPermission("notifyVoLteServiceStateChanged()")) {
   1266             return;
   1267         }
   1268         synchronized (mRecords) {
   1269             mVoLteServiceState = lteState;
   1270             for (Record r : mRecords) {
   1271                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_VOLTE_STATE)) {
   1272                     try {
   1273                         r.callback.onVoLteServiceStateChanged(
   1274                                 new VoLteServiceState(mVoLteServiceState));
   1275                     } catch (RemoteException ex) {
   1276                         mRemoveList.add(r.binder);
   1277                     }
   1278                 }
   1279             }
   1280             handleRemoveListLocked();
   1281         }
   1282     }
   1283 
   1284     public void notifyOemHookRawEventForSubscriber(int subId, byte[] rawData) {
   1285         if (!checkNotifyPermission("notifyOemHookRawEventForSubscriber")) {
   1286             return;
   1287         }
   1288 
   1289         synchronized (mRecords) {
   1290             for (Record r : mRecords) {
   1291                 if (VDBG) {
   1292                     log("notifyOemHookRawEventForSubscriber:  r=" + r + " subId=" + subId);
   1293                 }
   1294                 if ((r.matchPhoneStateListenerEvent(
   1295                         PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT)) &&
   1296                         ((r.subId == subId) ||
   1297                         (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID))) {
   1298                     try {
   1299                         r.callback.onOemHookRawEvent(rawData);
   1300                     } catch (RemoteException ex) {
   1301                         mRemoveList.add(r.binder);
   1302                     }
   1303                 }
   1304             }
   1305             handleRemoveListLocked();
   1306         }
   1307     }
   1308 
   1309     @Override
   1310     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1311         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
   1312                 != PackageManager.PERMISSION_GRANTED) {
   1313             pw.println("Permission Denial: can't dump telephony.registry from from pid="
   1314                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
   1315             return;
   1316         }
   1317         synchronized (mRecords) {
   1318             final int recordCount = mRecords.size();
   1319             pw.println("last known state:");
   1320             for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
   1321                 pw.println("  Phone Id=" + i);
   1322                 pw.println("  mCallState=" + mCallState[i]);
   1323                 pw.println("  mCallIncomingNumber=" + mCallIncomingNumber[i]);
   1324                 pw.println("  mServiceState=" + mServiceState[i]);
   1325                 pw.println("  mSignalStrength=" + mSignalStrength[i]);
   1326                 pw.println("  mMessageWaiting=" + mMessageWaiting[i]);
   1327                 pw.println("  mCallForwarding=" + mCallForwarding[i]);
   1328                 pw.println("  mDataActivity=" + mDataActivity[i]);
   1329                 pw.println("  mDataConnectionState=" + mDataConnectionState[i]);
   1330                 pw.println("  mDataConnectionPossible=" + mDataConnectionPossible[i]);
   1331                 pw.println("  mDataConnectionReason=" + mDataConnectionReason[i]);
   1332                 pw.println("  mDataConnectionApn=" + mDataConnectionApn[i]);
   1333                 pw.println("  mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]);
   1334                 pw.println("  mDataConnectionNetworkCapabilities=" +
   1335                         mDataConnectionNetworkCapabilities[i]);
   1336                 pw.println("  mCellLocation=" + mCellLocation[i]);
   1337                 pw.println("  mCellInfo=" + mCellInfo.get(i));
   1338             }
   1339             pw.println("registrations: count=" + recordCount);
   1340             for (Record r : mRecords) {
   1341                 pw.println("  " + r);
   1342             }
   1343         }
   1344     }
   1345 
   1346     //
   1347     // the legacy intent broadcasting
   1348     //
   1349 
   1350     private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) {
   1351         long ident = Binder.clearCallingIdentity();
   1352         try {
   1353             mBatteryStats.notePhoneState(state.getState());
   1354         } catch (RemoteException re) {
   1355             // Can't do much
   1356         } finally {
   1357             Binder.restoreCallingIdentity(ident);
   1358         }
   1359 
   1360         Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
   1361         Bundle data = new Bundle();
   1362         state.fillInNotifierBundle(data);
   1363         intent.putExtras(data);
   1364         // Pass the subscription along with the intent.
   1365         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
   1366         intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
   1367         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1368     }
   1369 
   1370     private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId,
   1371             int subId) {
   1372         long ident = Binder.clearCallingIdentity();
   1373         try {
   1374             mBatteryStats.notePhoneSignalStrength(signalStrength);
   1375         } catch (RemoteException e) {
   1376             /* The remote entity disappeared, we can safely ignore the exception. */
   1377         } finally {
   1378             Binder.restoreCallingIdentity(ident);
   1379         }
   1380 
   1381         Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
   1382         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
   1383         Bundle data = new Bundle();
   1384         signalStrength.fillInNotifierBundle(data);
   1385         intent.putExtras(data);
   1386         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
   1387         intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
   1388         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1389     }
   1390 
   1391     /**
   1392      * Broadcasts an intent notifying apps of a phone state change. {@code subId} can be
   1393      * a valid subId, in which case this function fires a subId-specific intent, or it
   1394      * can be {@code SubscriptionManager.INVALID_SUBSCRIPTION_ID}, in which case we send
   1395      * a global state change broadcast ({@code TelephonyManager.ACTION_PHONE_STATE_CHANGED}).
   1396      */
   1397     private void broadcastCallStateChanged(int state, String incomingNumber, int phoneId,
   1398                 int subId) {
   1399         long ident = Binder.clearCallingIdentity();
   1400         try {
   1401             if (state == TelephonyManager.CALL_STATE_IDLE) {
   1402                 mBatteryStats.notePhoneOff();
   1403             } else {
   1404                 mBatteryStats.notePhoneOn();
   1405             }
   1406         } catch (RemoteException e) {
   1407             /* The remote entity disappeared, we can safely ignore the exception. */
   1408         } finally {
   1409             Binder.restoreCallingIdentity(ident);
   1410         }
   1411 
   1412         Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
   1413         intent.putExtra(PhoneConstants.STATE_KEY,
   1414                 DefaultPhoneNotifier.convertCallState(state).toString());
   1415         if (!TextUtils.isEmpty(incomingNumber)) {
   1416             intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
   1417         }
   1418 
   1419         // If a valid subId was specified, we should fire off a subId-specific state
   1420         // change intent and include the subId.
   1421         if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
   1422             intent.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
   1423             intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
   1424         }
   1425         // If the phoneId is invalid, the broadcast is for overall call state.
   1426         if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
   1427             intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
   1428         }
   1429 
   1430         // Send broadcast twice, once for apps that have PRIVILEGED permission and once for those
   1431         // that have the runtime one
   1432         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
   1433                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
   1434         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
   1435                 android.Manifest.permission.READ_PHONE_STATE,
   1436                 AppOpsManager.OP_READ_PHONE_STATE);
   1437     }
   1438 
   1439     private void broadcastDataConnectionStateChanged(int state,
   1440             boolean isDataConnectivityPossible,
   1441             String reason, String apn, String apnType, LinkProperties linkProperties,
   1442             NetworkCapabilities networkCapabilities, boolean roaming, int subId) {
   1443         // Note: not reporting to the battery stats service here, because the
   1444         // status bar takes care of that after taking into account all of the
   1445         // required info.
   1446         Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
   1447         intent.putExtra(PhoneConstants.STATE_KEY,
   1448                 DefaultPhoneNotifier.convertDataState(state).toString());
   1449         if (!isDataConnectivityPossible) {
   1450             intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
   1451         }
   1452         if (reason != null) {
   1453             intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
   1454         }
   1455         if (linkProperties != null) {
   1456             intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
   1457             String iface = linkProperties.getInterfaceName();
   1458             if (iface != null) {
   1459                 intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface);
   1460             }
   1461         }
   1462         if (networkCapabilities != null) {
   1463             intent.putExtra(PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY, networkCapabilities);
   1464         }
   1465         if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true);
   1466 
   1467         intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
   1468         intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
   1469         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
   1470         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1471     }
   1472 
   1473     private void broadcastDataConnectionFailed(String reason, String apnType,
   1474             int subId) {
   1475         Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
   1476         intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason);
   1477         intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
   1478         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
   1479         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1480     }
   1481 
   1482     private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
   1483             int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
   1484         Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
   1485         intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
   1486         intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
   1487         intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
   1488         intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
   1489         intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
   1490         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
   1491                 android.Manifest.permission.READ_PRECISE_PHONE_STATE);
   1492     }
   1493 
   1494     private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
   1495             String apnType, String apn, String reason, LinkProperties linkProperties,
   1496             String failCause) {
   1497         Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
   1498         intent.putExtra(PhoneConstants.STATE_KEY, state);
   1499         intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
   1500         if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
   1501         if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
   1502         if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
   1503         if (linkProperties != null) {
   1504             intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY,linkProperties);
   1505         }
   1506         if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
   1507 
   1508         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
   1509                 android.Manifest.permission.READ_PRECISE_PHONE_STATE);
   1510     }
   1511 
   1512     private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
   1513         if  (checkNotifyPermission()) {
   1514             return;
   1515         }
   1516 
   1517         enforceCarrierPrivilege();
   1518     }
   1519 
   1520     private boolean checkNotifyPermission(String method) {
   1521         if (checkNotifyPermission()) {
   1522             return true;
   1523         }
   1524         String msg = "Modify Phone State Permission Denial: " + method + " from pid="
   1525                 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
   1526         if (DBG) log(msg);
   1527         return false;
   1528     }
   1529 
   1530     private boolean checkNotifyPermission() {
   1531         return mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
   1532                 == PackageManager.PERMISSION_GRANTED;
   1533     }
   1534 
   1535     private void enforceCarrierPrivilege() {
   1536         TelephonyManager tm = TelephonyManager.getDefault();
   1537         String[] pkgs = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
   1538         for (String pkg : pkgs) {
   1539             if (tm.checkCarrierPrivilegesForPackage(pkg) ==
   1540                     TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
   1541                 return;
   1542             }
   1543         }
   1544 
   1545         String msg = "Carrier Privilege Permission Denial: from pid=" + Binder.getCallingPid()
   1546                 + ", uid=" + Binder.getCallingUid();
   1547         if (DBG) log(msg);
   1548         throw new SecurityException(msg);
   1549     }
   1550 
   1551     private void checkListenerPermission(int events) {
   1552         if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
   1553             mContext.enforceCallingOrSelfPermission(
   1554                     android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
   1555 
   1556         }
   1557 
   1558         if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
   1559             mContext.enforceCallingOrSelfPermission(
   1560                     android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
   1561 
   1562         }
   1563 
   1564         if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
   1565             try {
   1566                 mContext.enforceCallingOrSelfPermission(
   1567                         android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
   1568                 // SKIP checking for run-time permission since caller or self has PRIVILEGED
   1569                 // permission
   1570             } catch (SecurityException e) {
   1571                 mContext.enforceCallingOrSelfPermission(
   1572                         android.Manifest.permission.READ_PHONE_STATE, null);
   1573             }
   1574         }
   1575 
   1576         if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
   1577             mContext.enforceCallingOrSelfPermission(
   1578                     android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
   1579 
   1580         }
   1581 
   1582         if ((events & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) {
   1583             mContext.enforceCallingOrSelfPermission(
   1584                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
   1585         }
   1586     }
   1587 
   1588     private void handleRemoveListLocked() {
   1589         int size = mRemoveList.size();
   1590         if (VDBG) log("handleRemoveListLocked: mRemoveList.size()=" + size);
   1591         if (size > 0) {
   1592             for (IBinder b: mRemoveList) {
   1593                 remove(b);
   1594             }
   1595             mRemoveList.clear();
   1596         }
   1597     }
   1598 
   1599     private boolean validateEventsAndUserLocked(Record r, int events) {
   1600         int foregroundUser;
   1601         long callingIdentity = Binder.clearCallingIdentity();
   1602         boolean valid = false;
   1603         try {
   1604             foregroundUser = ActivityManager.getCurrentUser();
   1605             valid = r.callerUserId ==  foregroundUser && r.matchPhoneStateListenerEvent(events);
   1606             if (DBG | DBG_LOC) {
   1607                 log("validateEventsAndUserLocked: valid=" + valid
   1608                         + " r.callerUserId=" + r.callerUserId + " foregroundUser=" + foregroundUser
   1609                         + " r.events=" + r.events + " events=" + events);
   1610             }
   1611         } finally {
   1612             Binder.restoreCallingIdentity(callingIdentity);
   1613         }
   1614         return valid;
   1615     }
   1616 
   1617     private boolean validatePhoneId(int phoneId) {
   1618         boolean valid = (phoneId >= 0) && (phoneId < mNumPhones);
   1619         if (VDBG) log("validatePhoneId: " + valid);
   1620         return valid;
   1621     }
   1622 
   1623     private static void log(String s) {
   1624         Rlog.d(TAG, s);
   1625     }
   1626 
   1627     private static class LogSSC {
   1628         private Time mTime;
   1629         private String mS;
   1630         private int mSubId;
   1631         private int mPhoneId;
   1632         private ServiceState mState;
   1633 
   1634         public void set(Time t, String s, int subId, int phoneId, ServiceState state) {
   1635             mTime = t; mS = s; mSubId = subId; mPhoneId = phoneId; mState = state;
   1636         }
   1637 
   1638         @Override
   1639         public String toString() {
   1640             return mS + " Time " + mTime.toString() + " mSubId " + mSubId + " mPhoneId "
   1641                     + mPhoneId + "  mState " + mState;
   1642         }
   1643     }
   1644 
   1645     private LogSSC logSSC [] = new LogSSC[10];
   1646     private int next = 0;
   1647 
   1648     private void logServiceStateChanged(String s, int subId, int phoneId, ServiceState state) {
   1649         if (logSSC == null || logSSC.length == 0) {
   1650             return;
   1651         }
   1652         if (logSSC[next] == null) {
   1653             logSSC[next] = new LogSSC();
   1654         }
   1655         Time t = new Time();
   1656         t.setToNow();
   1657         logSSC[next].set(t, s, subId, phoneId, state);
   1658         if (++next >= logSSC.length) {
   1659             next = 0;
   1660         }
   1661     }
   1662 
   1663     private void toStringLogSSC(String prompt) {
   1664         if (logSSC == null || logSSC.length == 0 || (next == 0 && logSSC[next] == null)) {
   1665             log(prompt + ": logSSC is empty");
   1666         } else {
   1667             // There is at least one element
   1668             log(prompt + ": logSSC.length=" + logSSC.length + " next=" + next);
   1669             int i = next;
   1670             if (logSSC[i] == null) {
   1671                 // logSSC is not full so back to the beginning
   1672                 i = 0;
   1673             }
   1674             do {
   1675                 log(logSSC[i].toString());
   1676                 if (++i >= logSSC.length) {
   1677                     i = 0;
   1678                 }
   1679             } while (i != next);
   1680             log(prompt + ": ----------------");
   1681         }
   1682     }
   1683 
   1684     boolean idMatch(int rSubId, int subId, int phoneId) {
   1685 
   1686         if(subId < 0) {
   1687             // Invalid case, we need compare phoneId with default one.
   1688             return (mDefaultPhoneId == phoneId);
   1689         }
   1690         if(rSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
   1691             return (subId == mDefaultSubId);
   1692         } else {
   1693             return (rSubId == subId);
   1694         }
   1695     }
   1696 
   1697     private void checkPossibleMissNotify(Record r, int phoneId) {
   1698         int events = r.events;
   1699 
   1700         if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
   1701             try {
   1702                 if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" +
   1703                         mServiceState[phoneId]);
   1704                 r.callback.onServiceStateChanged(
   1705                         new ServiceState(mServiceState[phoneId]));
   1706             } catch (RemoteException ex) {
   1707                 mRemoveList.add(r.binder);
   1708             }
   1709         }
   1710 
   1711         if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
   1712             try {
   1713                 SignalStrength signalStrength = mSignalStrength[phoneId];
   1714                 if (DBG) {
   1715                     log("checkPossibleMissNotify: onSignalStrengthsChanged SS=" + signalStrength);
   1716                 }
   1717                 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
   1718             } catch (RemoteException ex) {
   1719                 mRemoveList.add(r.binder);
   1720             }
   1721         }
   1722 
   1723         if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
   1724             try {
   1725                 int gsmSignalStrength = mSignalStrength[phoneId]
   1726                         .getGsmSignalStrength();
   1727                 if (DBG) {
   1728                     log("checkPossibleMissNotify: onSignalStrengthChanged SS=" +
   1729                             gsmSignalStrength);
   1730                 }
   1731                 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
   1732                         : gsmSignalStrength));
   1733             } catch (RemoteException ex) {
   1734                 mRemoveList.add(r.binder);
   1735             }
   1736         }
   1737 
   1738         if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
   1739             try {
   1740                 if (DBG_LOC) {
   1741                     log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
   1742                             + mCellInfo.get(phoneId));
   1743                 }
   1744                 r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
   1745             } catch (RemoteException ex) {
   1746                 mRemoveList.add(r.binder);
   1747             }
   1748         }
   1749 
   1750         if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
   1751             try {
   1752                 if (VDBG) {
   1753                     log("checkPossibleMissNotify: onMessageWaitingIndicatorChanged phoneId="
   1754                             + phoneId + " mwi=" + mMessageWaiting[phoneId]);
   1755                 }
   1756                 r.callback.onMessageWaitingIndicatorChanged(
   1757                         mMessageWaiting[phoneId]);
   1758             } catch (RemoteException ex) {
   1759                 mRemoveList.add(r.binder);
   1760             }
   1761         }
   1762 
   1763         if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
   1764             try {
   1765                 if (VDBG) {
   1766                     log("checkPossibleMissNotify: onCallForwardingIndicatorChanged phoneId="
   1767                         + phoneId + " cfi=" + mCallForwarding[phoneId]);
   1768                 }
   1769                 r.callback.onCallForwardingIndicatorChanged(
   1770                         mCallForwarding[phoneId]);
   1771             } catch (RemoteException ex) {
   1772                 mRemoveList.add(r.binder);
   1773             }
   1774         }
   1775 
   1776         if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
   1777             try {
   1778                 if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
   1779                         + mCellLocation[phoneId]);
   1780                 r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
   1781             } catch (RemoteException ex) {
   1782                 mRemoveList.add(r.binder);
   1783             }
   1784         }
   1785 
   1786         if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
   1787             try {
   1788                 if (DBG) {
   1789                     log("checkPossibleMissNotify: onDataConnectionStateChanged(mDataConnectionState"
   1790                             + "=" + mDataConnectionState[phoneId]
   1791                             + ", mDataConnectionNetworkType=" + mDataConnectionNetworkType[phoneId]
   1792                             + ")");
   1793                 }
   1794                 r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
   1795                         mDataConnectionNetworkType[phoneId]);
   1796             } catch (RemoteException ex) {
   1797                 mRemoveList.add(r.binder);
   1798             }
   1799         }
   1800     }
   1801 }
   1802