Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2016 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.facade.telephony;
     18 
     19 import android.app.Activity;
     20 import android.app.Service;
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.database.Cursor;
     25 import android.net.Uri;
     26 import android.os.RemoteException;
     27 import android.provider.ContactsContract;
     28 import android.telephony.CellInfo;
     29 import android.telephony.CellLocation;
     30 import android.telephony.ModemActivityInfo;
     31 import android.telephony.NeighboringCellInfo;
     32 import android.telephony.PhoneStateListener;
     33 import android.telephony.SignalStrength;
     34 import android.telephony.SubscriptionManager;
     35 import android.telephony.TelephonyManager;
     36 import android.provider.Telephony;
     37 import android.telephony.SubscriptionInfo;
     38 import android.telecom.VideoProfile;
     39 import android.telecom.TelecomManager;
     40 import android.util.Base64;
     41 
     42 import com.android.internal.telephony.PhoneConstants;
     43 import com.android.internal.telephony.RILConstants;
     44 import com.android.internal.telephony.TelephonyProperties;
     45 import com.google.common.io.BaseEncoding;
     46 
     47 import android.content.ContentValues;
     48 import android.os.SystemProperties;
     49 
     50 import com.googlecode.android_scripting.facade.AndroidFacade;
     51 import com.googlecode.android_scripting.facade.EventFacade;
     52 import com.googlecode.android_scripting.facade.FacadeManager;
     53 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     54                                                    .CallStateChangeListener;
     55 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     56                                                    .CellInfoChangeListener;
     57 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     58                                                    .DataConnectionRealTimeInfoChangeListener;
     59 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     60                                                    .DataConnectionStateChangeListener;
     61 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     62                                                    .ServiceStateChangeListener;
     63 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     64                                                    .SignalStrengthChangeListener;
     65 import com.googlecode.android_scripting.facade.telephony.TelephonyStateListeners
     66                                                    .VoiceMailStateChangeListener;
     67 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
     68 import com.googlecode.android_scripting.rpc.Rpc;
     69 import com.googlecode.android_scripting.rpc.RpcDefault;
     70 import com.googlecode.android_scripting.rpc.RpcParameter;
     71 import com.googlecode.android_scripting.Log;
     72 import com.googlecode.android_scripting.MainThread;
     73 import com.googlecode.android_scripting.rpc.RpcOptional;
     74 
     75 import java.io.UnsupportedEncodingException;
     76 import java.lang.reflect.Field;
     77 import java.net.URLEncoder;
     78 import java.util.List;
     79 import java.util.concurrent.Callable;
     80 import java.util.HashMap;
     81 
     82 /**
     83  * Exposes TelephonyManager functionality.
     84  *
     85  * @author Damon Kohler (damonkohler (at) gmail.com)
     86  * @author Felix Arends (felix.arends (at) gmail.com)
     87  */
     88 public class TelephonyManagerFacade extends RpcReceiver {
     89 
     90     private final Service mService;
     91     private final AndroidFacade mAndroidFacade;
     92     private final EventFacade mEventFacade;
     93     private final TelephonyManager mTelephonyManager;
     94     private final SubscriptionManager mSubscriptionManager;
     95     private HashMap<Integer, StateChangeListener> mStateChangeListeners =
     96                              new HashMap<Integer, StateChangeListener>();
     97 
     98     private static final String[] sProjection = new String[] {
     99             Telephony.Carriers._ID, // 0
    100             Telephony.Carriers.NAME, // 1
    101             Telephony.Carriers.APN, // 2
    102             Telephony.Carriers.PROXY, // 3
    103             Telephony.Carriers.PORT, // 4
    104             Telephony.Carriers.USER, // 5
    105             Telephony.Carriers.SERVER, // 6
    106             Telephony.Carriers.PASSWORD, // 7
    107             Telephony.Carriers.MMSC, // 8
    108             Telephony.Carriers.MCC, // 9
    109             Telephony.Carriers.MNC, // 10
    110             Telephony.Carriers.NUMERIC, // 11
    111             Telephony.Carriers.MMSPROXY,// 12
    112             Telephony.Carriers.MMSPORT, // 13
    113             Telephony.Carriers.AUTH_TYPE, // 14
    114             Telephony.Carriers.TYPE, // 15
    115             Telephony.Carriers.PROTOCOL, // 16
    116             Telephony.Carriers.CARRIER_ENABLED, // 17
    117             Telephony.Carriers.BEARER_BITMASK, // 18
    118             Telephony.Carriers.ROAMING_PROTOCOL, // 19
    119             Telephony.Carriers.MVNO_TYPE, // 20
    120             Telephony.Carriers.MVNO_MATCH_DATA // 21
    121     };
    122 
    123     public TelephonyManagerFacade(FacadeManager manager) {
    124         super(manager);
    125         mService = manager.getService();
    126         mTelephonyManager =
    127                 (TelephonyManager) mService.getSystemService(Context.TELEPHONY_SERVICE);
    128         mAndroidFacade = manager.getReceiver(AndroidFacade.class);
    129         mEventFacade = manager.getReceiver(EventFacade.class);
    130         mSubscriptionManager = SubscriptionManager.from(mService);
    131     }
    132 
    133     @Rpc(description = "Set network preference.")
    134     public boolean telephonySetPreferredNetworkTypes(
    135         @RpcParameter(name = "nwPreference") String nwPreference) {
    136         return telephonySetPreferredNetworkTypesForSubscription(nwPreference,
    137                 SubscriptionManager.getDefaultSubscriptionId());
    138     }
    139 
    140     @Rpc(description = "Set network preference for subscription.")
    141     public boolean telephonySetPreferredNetworkTypesForSubscription(
    142             @RpcParameter(name = "nwPreference") String nwPreference,
    143             @RpcParameter(name = "subId") Integer subId) {
    144         int networkPreferenceInt = TelephonyUtils.getNetworkModeIntfromString(
    145             nwPreference);
    146         if (RILConstants.RIL_ERRNO_INVALID_RESPONSE != networkPreferenceInt) {
    147             return mTelephonyManager.setPreferredNetworkType(
    148                 subId, networkPreferenceInt);
    149         } else {
    150             return false;
    151         }
    152     }
    153 
    154     @Rpc(description = "Get network preference.")
    155     public String telephonyGetPreferredNetworkTypes() {
    156         return telephonyGetPreferredNetworkTypesForSubscription(
    157                 SubscriptionManager.getDefaultSubscriptionId());
    158     }
    159 
    160     @Rpc(description = "Get network preference for subscription.")
    161     public String telephonyGetPreferredNetworkTypesForSubscription(
    162             @RpcParameter(name = "subId") Integer subId) {
    163         int networkPreferenceInt = mTelephonyManager.getPreferredNetworkType(subId);
    164         return TelephonyUtils.getNetworkModeStringfromInt(networkPreferenceInt);
    165     }
    166 
    167     @Rpc(description = "Get current voice network type")
    168     public String telephonyGetCurrentVoiceNetworkType() {
    169         return telephonyGetCurrentVoiceNetworkTypeForSubscription(
    170                 SubscriptionManager.getDefaultSubscriptionId());
    171     }
    172 
    173     @Rpc(description = "Get current voice network type for subscription")
    174     public String telephonyGetCurrentVoiceNetworkTypeForSubscription(
    175             @RpcParameter(name = "subId") Integer subId) {
    176         return TelephonyUtils.getNetworkTypeString(
    177             mTelephonyManager.getVoiceNetworkType(subId));
    178     }
    179 
    180     @Rpc(description = "Get current data network type")
    181     public String telephonyGetCurrentDataNetworkType() {
    182         return telephonyGetCurrentDataNetworkTypeForSubscription(
    183                 SubscriptionManager.getDefaultSubscriptionId());
    184     }
    185 
    186     @Rpc(description = "Get current data network type for subscription")
    187     public String telephonyGetCurrentDataNetworkTypeForSubscription(
    188             @RpcParameter(name = "subId") Integer subId) {
    189         return TelephonyUtils.getNetworkTypeString(
    190             mTelephonyManager.getDataNetworkType(subId));
    191     }
    192 
    193     @Rpc(description = "Get if phone have voice capability")
    194     public Boolean telephonyIsVoiceCapable() {
    195         return mTelephonyManager.isVoiceCapable();
    196     }
    197 
    198     @Rpc(description = "Get preferred network setting for " +
    199                        "default subscription ID .Return value is integer.")
    200     public int telephonyGetPreferredNetworkTypeInteger() {
    201         return telephonyGetPreferredNetworkTypeIntegerForSubscription(
    202                                          SubscriptionManager.getDefaultSubscriptionId());
    203     }
    204 
    205     @Rpc(description = "Get preferred network setting for " +
    206                        "specified subscription ID .Return value is integer.")
    207     public int telephonyGetPreferredNetworkTypeIntegerForSubscription(
    208                @RpcParameter(name = "subId") Integer subId) {
    209         return mTelephonyManager.getPreferredNetworkType(subId);
    210     }
    211 
    212     @Rpc(description = "Starts tracking call state change" +
    213                        "for default subscription ID.")
    214     public Boolean telephonyStartTrackingCallState() {
    215         return telephonyStartTrackingCallStateForSubscription(
    216                               SubscriptionManager.getDefaultVoiceSubscriptionId());
    217     }
    218 
    219     @Rpc(description = "Starts tracking call state change" +
    220                        "for specified subscription ID.")
    221     public Boolean telephonyStartTrackingCallStateForSubscription(
    222                 @RpcParameter(name = "subId") Integer subId) {
    223         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    224         if(listener == null) {
    225             Log.e("Invalid subscription ID");
    226             return false;
    227         }
    228         mTelephonyManager.listen(
    229             listener.mCallStateChangeListener,
    230             CallStateChangeListener.sListeningStates);
    231         return true;
    232     }
    233 
    234     @Rpc(description = "Starts tracking cell info change" +
    235                        "for default subscription ID.")
    236     public Boolean telephonyStartTrackingCellInfoChange() {
    237         return telephonyStartTrackingCellInfoChangeForSubscription(
    238                               SubscriptionManager.getDefaultVoiceSubscriptionId());
    239     }
    240 
    241     @Rpc(description = "Starts tracking cell info change" +
    242                        "for specified subscription ID.")
    243     public Boolean telephonyStartTrackingCellInfoChangeForSubscription(
    244                 @RpcParameter(name = "subId") Integer subId) {
    245         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    246         if(listener == null) {
    247             Log.e("Invalid subscription ID");
    248             return false;
    249         }
    250         mTelephonyManager.listen(
    251             listener.mCellInfoChangeListener,
    252             PhoneStateListener.LISTEN_CELL_INFO);
    253         return true;
    254     }
    255 
    256     @Rpc(description = "Turn on/off precise listening on fore/background or" +
    257                        " ringing calls for default voice subscription ID.")
    258     public Boolean telephonyAdjustPreciseCallStateListenLevel(String type,
    259                                                           Boolean listen) {
    260         return telephonyAdjustPreciseCallStateListenLevelForSubscription(type, listen,
    261                                  SubscriptionManager.getDefaultVoiceSubscriptionId());
    262     }
    263 
    264     @Rpc(description = "Turn on/off precise listening on fore/background or" +
    265                        " ringing calls for specified subscription ID.")
    266     public Boolean telephonyAdjustPreciseCallStateListenLevelForSubscription(String type,
    267                    Boolean listen,
    268                    @RpcParameter(name = "subId") Integer subId) {
    269         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    270         if(listener == null) {
    271             Log.e("Invalid subscription ID");
    272             return false;
    273         }
    274 
    275         if (type.equals(TelephonyConstants.PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND)) {
    276             listener.mCallStateChangeListener.listenForeground = listen;
    277         } else if (type.equals(TelephonyConstants.PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING)) {
    278             listener.mCallStateChangeListener.listenRinging = listen;
    279         } else if (type.equals(TelephonyConstants.PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND)) {
    280             listener.mCallStateChangeListener.listenBackground = listen;
    281         } else {
    282             throw new IllegalArgumentException("Invalid listen level type " + type);
    283         }
    284 
    285         return true;
    286     }
    287 
    288     @Rpc(description = "Stops tracking cell info change " +
    289             "for default voice subscription ID.")
    290     public Boolean telephonyStopTrackingCellInfoChange() {
    291         return telephonyStopTrackingCellInfoChangeForSubscription(
    292                 SubscriptionManager.getDefaultVoiceSubscriptionId());
    293     }
    294 
    295     @Rpc(description = "Stops tracking cell info change " +
    296                        "for specified subscription ID.")
    297     public Boolean telephonyStopTrackingCellInfoChangeForSubscription(
    298                    @RpcParameter(name = "subId") Integer subId) {
    299         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    300         if(listener == null) {
    301             Log.e("Invalid subscription ID");
    302             return false;
    303         }
    304         mTelephonyManager.listen(
    305             listener.mCellInfoChangeListener,
    306             PhoneStateListener.LISTEN_NONE);
    307         return true;
    308     }
    309     @Rpc(description = "Stops tracking call state change " +
    310             "for default voice subscription ID.")
    311     public Boolean telephonyStopTrackingCallStateChange() {
    312         return telephonyStopTrackingCallStateChangeForSubscription(
    313                 SubscriptionManager.getDefaultVoiceSubscriptionId());
    314     }
    315 
    316     @Rpc(description = "Stops tracking call state change " +
    317                        "for specified subscription ID.")
    318     public Boolean telephonyStopTrackingCallStateChangeForSubscription(
    319                    @RpcParameter(name = "subId") Integer subId) {
    320         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    321         if(listener == null) {
    322             Log.e("Invalid subscription ID");
    323             return false;
    324         }
    325         mTelephonyManager.listen(
    326             listener.mCallStateChangeListener,
    327             PhoneStateListener.LISTEN_NONE);
    328         return true;
    329     }
    330 
    331     @Rpc(description = "Starts tracking data connection real time info change" +
    332                        "for default subscription ID.")
    333     public Boolean telephonyStartTrackingDataConnectionRTInfoChange() {
    334         return telephonyStartTrackingDataConnectionRTInfoChangeForSubscription(
    335                                  SubscriptionManager.getDefaultDataSubscriptionId());
    336     }
    337 
    338     @Rpc(description = "Starts tracking data connection real time info change" +
    339                        "for specified subscription ID.")
    340     public Boolean telephonyStartTrackingDataConnectionRTInfoChangeForSubscription(
    341                    @RpcParameter(name = "subId") Integer subId) {
    342         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    343         if(listener == null) {
    344             Log.e("Invalid subscription ID");
    345             return false;
    346         }
    347         mTelephonyManager.listen(
    348             listener.mDataConnectionRTInfoChangeListener,
    349             DataConnectionRealTimeInfoChangeListener.sListeningStates);
    350         return true;
    351     }
    352 
    353     @Rpc(description = "Stops tracking data connection real time info change" +
    354                        "for default subscription ID.")
    355     public Boolean telephonyStopTrackingDataConnectionRTInfoChange() {
    356         return telephonyStopTrackingDataConnectionRTInfoChangeForSubscription(
    357                                  SubscriptionManager.getDefaultDataSubscriptionId());
    358     }
    359 
    360     @Rpc(description = "Stops tracking data connection real time info change" +
    361                        "for specified subscription ID.")
    362     public Boolean telephonyStopTrackingDataConnectionRTInfoChangeForSubscription(
    363                    @RpcParameter(name = "subId") Integer subId) {
    364         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    365         if(listener == null) {
    366             Log.e("Invalid subscription ID");
    367             return false;
    368         }
    369         mTelephonyManager.listen(
    370             listener.mDataConnectionRTInfoChangeListener,
    371             PhoneStateListener.LISTEN_NONE);
    372         return true;
    373     }
    374 
    375     @Rpc(description = "Starts tracking data connection state change" +
    376                        "for default subscription ID..")
    377     public Boolean telephonyStartTrackingDataConnectionStateChange() {
    378         return telephonyStartTrackingDataConnectionStateChangeForSubscription(
    379                                  SubscriptionManager.getDefaultDataSubscriptionId());
    380     }
    381 
    382     @Rpc(description = "Starts tracking data connection state change" +
    383                        "for specified subscription ID.")
    384     public Boolean telephonyStartTrackingDataConnectionStateChangeForSubscription(
    385                    @RpcParameter(name = "subId") Integer subId) {
    386         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    387         if(listener == null) {
    388             Log.e("Invalid subscription ID");
    389             return false;
    390         }
    391         mTelephonyManager.listen(
    392             listener.mDataConnectionStateChangeListener,
    393             DataConnectionStateChangeListener.sListeningStates);
    394         return true;
    395     }
    396 
    397     @Rpc(description = "Stops tracking data connection state change " +
    398                        "for default subscription ID..")
    399     public Boolean telephonyStopTrackingDataConnectionStateChange() {
    400         return telephonyStopTrackingDataConnectionStateChangeForSubscription(
    401                                  SubscriptionManager.getDefaultDataSubscriptionId());
    402     }
    403 
    404     @Rpc(description = "Stops tracking data connection state change " +
    405                        "for specified subscription ID..")
    406     public Boolean telephonyStopTrackingDataConnectionStateChangeForSubscription(
    407                    @RpcParameter(name = "subId") Integer subId) {
    408         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    409         if(listener == null) {
    410             Log.e("Invalid subscription ID");
    411             return false;
    412         }
    413         mTelephonyManager.listen(
    414             listener.mDataConnectionStateChangeListener,
    415             PhoneStateListener.LISTEN_NONE);
    416         return true;
    417     }
    418 
    419     @Rpc(description = "Starts tracking service state change " +
    420                        "for default subscription ID.")
    421     public Boolean telephonyStartTrackingServiceStateChange() {
    422         return telephonyStartTrackingServiceStateChangeForSubscription(
    423                                  SubscriptionManager.getDefaultSubscriptionId());
    424     }
    425 
    426     @Rpc(description = "Starts tracking service state change " +
    427                        "for specified subscription ID.")
    428     public Boolean telephonyStartTrackingServiceStateChangeForSubscription(
    429                    @RpcParameter(name = "subId") Integer subId) {
    430         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    431         if(listener == null) {
    432             Log.e("Invalid subscription ID");
    433             return false;
    434         }
    435         mTelephonyManager.listen(
    436             listener.mServiceStateChangeListener,
    437             ServiceStateChangeListener.sListeningStates);
    438         return true;
    439     }
    440 
    441     @Rpc(description = "Stops tracking service state change " +
    442                        "for default subscription ID.")
    443     public Boolean telephonyStopTrackingServiceStateChange() {
    444         return telephonyStopTrackingServiceStateChangeForSubscription(
    445                                  SubscriptionManager.getDefaultSubscriptionId());
    446     }
    447 
    448     @Rpc(description = "Stops tracking service state change " +
    449                        "for specified subscription ID.")
    450     public Boolean telephonyStopTrackingServiceStateChangeForSubscription(
    451                    @RpcParameter(name = "subId") Integer subId) {
    452         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    453         if(listener == null) {
    454             Log.e("Invalid subscription ID");
    455             return false;
    456         }
    457         mTelephonyManager.listen(
    458             listener.mServiceStateChangeListener,
    459             PhoneStateListener.LISTEN_NONE);
    460             return true;
    461     }
    462 
    463     @Rpc(description = "Starts tracking signal strength change " +
    464                        "for default subscription ID.")
    465     public Boolean telephonyStartTrackingSignalStrengthChange() {
    466         return telephonyStartTrackingSignalStrengthChangeForSubscription(
    467                                  SubscriptionManager.getDefaultSubscriptionId());
    468     }
    469 
    470     @Rpc(description = "Starts tracking signal strength change " +
    471                        "for specified subscription ID.")
    472     public Boolean telephonyStartTrackingSignalStrengthChangeForSubscription(
    473                    @RpcParameter(name = "subId") Integer subId) {
    474         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    475         if(listener == null) {
    476             Log.e("Invalid subscription ID");
    477             return false;
    478         }
    479         mTelephonyManager.listen(
    480             listener.mSignalStrengthChangeListener,
    481             SignalStrengthChangeListener.sListeningStates);
    482         return true;
    483     }
    484 
    485     @Rpc(description = "Stops tracking signal strength change " +
    486                        "for default subscription ID.")
    487     public Boolean telephonyStopTrackingSignalStrengthChange() {
    488         return telephonyStopTrackingSignalStrengthChangeForSubscription(
    489                                  SubscriptionManager.getDefaultSubscriptionId());
    490     }
    491 
    492     @Rpc(description = "Stops tracking signal strength change " +
    493                        "for specified subscription ID.")
    494     public Boolean telephonyStopTrackingSignalStrengthChangeForSubscription(
    495                    @RpcParameter(name = "subId") Integer subId) {
    496         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    497         if(listener == null) {
    498             Log.e("Invalid subscription ID");
    499             return false;
    500         }
    501         mTelephonyManager.listen(
    502             listener.mSignalStrengthChangeListener,
    503             PhoneStateListener.LISTEN_NONE);
    504         return true;
    505     }
    506 
    507     @Rpc(description = "Starts tracking voice mail state change " +
    508                        "for default subscription ID.")
    509     public Boolean telephonyStartTrackingVoiceMailStateChange() {
    510         return telephonyStartTrackingVoiceMailStateChangeForSubscription(
    511                                  SubscriptionManager.getDefaultSubscriptionId());
    512     }
    513 
    514     @Rpc(description = "Starts tracking voice mail state change " +
    515                        "for specified subscription ID.")
    516     public Boolean telephonyStartTrackingVoiceMailStateChangeForSubscription(
    517                    @RpcParameter(name = "subId") Integer subId) {
    518         StateChangeListener listener = getStateChangeListenerForSubscription(subId, true);
    519         if(listener == null) {
    520             Log.e("Invalid subscription ID");
    521             return false;
    522         }
    523         mTelephonyManager.listen(
    524             listener.mVoiceMailStateChangeListener,
    525             VoiceMailStateChangeListener.sListeningStates);
    526         return true;
    527     }
    528 
    529     @Rpc(description = "Stops tracking voice mail state change " +
    530                        "for default subscription ID.")
    531     public Boolean telephonyStopTrackingVoiceMailStateChange() {
    532         return telephonyStopTrackingVoiceMailStateChangeForSubscription(
    533                                  SubscriptionManager.getDefaultSubscriptionId());
    534     }
    535 
    536     @Rpc(description = "Stops tracking voice mail state change " +
    537                        "for specified subscription ID.")
    538     public Boolean telephonyStopTrackingVoiceMailStateChangeForSubscription(
    539                    @RpcParameter(name = "subId") Integer subId) {
    540         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
    541         if(listener == null) {
    542             Log.e("Invalid subscription ID");
    543             return false;
    544         }
    545         mTelephonyManager.listen(
    546             listener.mVoiceMailStateChangeListener,
    547             PhoneStateListener.LISTEN_NONE);
    548         return true;
    549     }
    550 
    551     @Rpc(description = "Answers an incoming ringing call.")
    552     public void telephonyAnswerCall() throws RemoteException {
    553         mTelephonyManager.silenceRinger();
    554         mTelephonyManager.answerRingingCall();
    555     }
    556 
    557     @Rpc(description = "Returns the current cell location.")
    558     public CellLocation telephonyGetCellLocation() {
    559         return mTelephonyManager.getCellLocation();
    560     }
    561 
    562     @Rpc(description = "Returns the numeric name (MCC+MNC) of registered operator." +
    563                        "for default subscription ID")
    564     public String telephonyGetNetworkOperator() {
    565         return telephonyGetNetworkOperatorForSubscription(
    566                         SubscriptionManager.getDefaultSubscriptionId());
    567     }
    568 
    569     @Rpc(description = "Returns the numeric name (MCC+MNC) of registered operator" +
    570                        "for specified subscription ID.")
    571     public String telephonyGetNetworkOperatorForSubscription(
    572                   @RpcParameter(name = "subId") Integer subId) {
    573         return mTelephonyManager.getNetworkOperator(subId);
    574     }
    575 
    576     @Rpc(description = "Returns the alphabetic name of current registered operator" +
    577                        "for specified subscription ID.")
    578     public String telephonyGetNetworkOperatorName() {
    579         return telephonyGetNetworkOperatorNameForSubscription(
    580                         SubscriptionManager.getDefaultSubscriptionId());
    581     }
    582 
    583     @Rpc(description = "Returns the alphabetic name of registered operator " +
    584                        "for specified subscription ID.")
    585     public String telephonyGetNetworkOperatorNameForSubscription(
    586                   @RpcParameter(name = "subId") Integer subId) {
    587         return mTelephonyManager.getNetworkOperatorName(subId);
    588     }
    589 
    590     @Rpc(description = "Returns the current RAT in use on the device.+" +
    591                        "for default subscription ID")
    592     public String telephonyGetNetworkType() {
    593 
    594         Log.d("sl4a:getNetworkType() is deprecated!" +
    595                 "Please use getVoiceNetworkType()" +
    596                 " or getDataNetworkTpe()");
    597 
    598         return telephonyGetNetworkTypeForSubscription(
    599                        SubscriptionManager.getDefaultSubscriptionId());
    600     }
    601 
    602     @Rpc(description = "Returns the current RAT in use on the device" +
    603             " for a given Subscription.")
    604     public String telephonyGetNetworkTypeForSubscription(
    605                   @RpcParameter(name = "subId") Integer subId) {
    606 
    607         Log.d("sl4a:getNetworkTypeForSubscriber() is deprecated!" +
    608                 "Please use getVoiceNetworkType()" +
    609                 " or getDataNetworkTpe()");
    610 
    611         return TelephonyUtils.getNetworkTypeString(
    612             mTelephonyManager.getNetworkType(subId));
    613     }
    614 
    615     @Rpc(description = "Returns the current voice RAT for" +
    616             " the default voice subscription.")
    617     public String telephonyGetVoiceNetworkType() {
    618         return telephonyGetVoiceNetworkTypeForSubscription(
    619                          SubscriptionManager.getDefaultVoiceSubscriptionId());
    620     }
    621 
    622     @Rpc(description = "Returns the current voice RAT for" +
    623             " the specified voice subscription.")
    624     public String telephonyGetVoiceNetworkTypeForSubscription(
    625                   @RpcParameter(name = "subId") Integer subId) {
    626         return TelephonyUtils.getNetworkTypeString(
    627             mTelephonyManager.getVoiceNetworkType(subId));
    628     }
    629 
    630     @Rpc(description = "Returns the current data RAT for" +
    631             " the defaut data subscription")
    632     public String telephonyGetDataNetworkType() {
    633         return telephonyGetDataNetworkTypeForSubscription(
    634                          SubscriptionManager.getDefaultDataSubscriptionId());
    635     }
    636 
    637     @Rpc(description = "Returns the current data RAT for" +
    638             " the specified data subscription")
    639     public String telephonyGetDataNetworkTypeForSubscription(
    640                   @RpcParameter(name = "subId") Integer subId) {
    641         return TelephonyUtils.getNetworkTypeString(
    642             mTelephonyManager.getDataNetworkType(subId));
    643     }
    644 
    645     @Rpc(description = "Returns the device phone type.")
    646     public String telephonyGetPhoneType() {
    647         return TelephonyUtils.getPhoneTypeString(
    648             mTelephonyManager.getPhoneType());
    649     }
    650 
    651     @Rpc(description = "Returns the MCC for default subscription ID")
    652     public String telephonyGetSimCountryIso() {
    653          return telephonyGetSimCountryIsoForSubscription(
    654                       SubscriptionManager.getDefaultSubscriptionId());
    655     }
    656 
    657     @Rpc(description = "Returns the MCC for specified subscription ID")
    658     public String telephonyGetSimCountryIsoForSubscription(
    659                   @RpcParameter(name = "subId") Integer subId) {
    660         return mTelephonyManager.getSimCountryIso(subId);
    661     }
    662 
    663     @Rpc(description = "Returns the MCC+MNC for default subscription ID")
    664     public String telephonyGetSimOperator() {
    665         return telephonyGetSimOperatorForSubscription(
    666                   SubscriptionManager.getDefaultSubscriptionId());
    667     }
    668 
    669     @Rpc(description = "Returns the MCC+MNC for specified subscription ID")
    670     public String telephonyGetSimOperatorForSubscription(
    671                   @RpcParameter(name = "subId") Integer subId) {
    672         return mTelephonyManager.getSimOperator(subId);
    673     }
    674 
    675     @Rpc(description = "Returns the Service Provider Name (SPN)" +
    676                        "for default subscription ID")
    677     public String telephonyGetSimOperatorName() {
    678         return telephonyGetSimOperatorNameForSubscription(
    679                   SubscriptionManager.getDefaultSubscriptionId());
    680     }
    681 
    682     @Rpc(description = "Returns the Service Provider Name (SPN)" +
    683                        " for specified subscription ID.")
    684     public String telephonyGetSimOperatorNameForSubscription(
    685                   @RpcParameter(name = "subId") Integer subId) {
    686         return mTelephonyManager.getSimOperatorName(subId);
    687     }
    688 
    689     @Rpc(description = "Returns the serial number of the SIM for " +
    690                        "default subscription ID, or Null if unavailable")
    691     public String telephonyGetSimSerialNumber() {
    692         return telephonyGetSimSerialNumberForSubscription(
    693                   SubscriptionManager.getDefaultSubscriptionId());
    694     }
    695 
    696     @Rpc(description = "Returns the serial number of the SIM for " +
    697                        "specified subscription ID, or Null if unavailable")
    698     public String telephonyGetSimSerialNumberForSubscription(
    699                   @RpcParameter(name = "subId") Integer subId) {
    700         return mTelephonyManager.getSimSerialNumber(subId);
    701     }
    702 
    703     @Rpc(description = "Returns the state of the SIM card for default slot ID.")
    704     public String telephonyGetSimState() {
    705         return telephonyGetSimStateForSlotId(
    706                   mTelephonyManager.getDefaultSim());
    707     }
    708 
    709     @Rpc(description = "Returns the state of the SIM card for specified slot ID.")
    710     public String telephonyGetSimStateForSlotId(
    711                   @RpcParameter(name = "slotId") Integer slotId) {
    712         return TelephonyUtils.getSimStateString(
    713             mTelephonyManager.getSimState(slotId));
    714     }
    715 
    716     @Rpc(description = "Get Authentication Challenge Response from a " +
    717             "given SIM Application")
    718     public String telephonyGetIccSimChallengeResponse(
    719             @RpcParameter(name = "appType") Integer appType,
    720             @RpcParameter(name = "authType") Integer authType,
    721             @RpcParameter(name = "hexChallenge") String hexChallenge) {
    722         return telephonyGetIccSimChallengeResponseForSubscription(
    723                 SubscriptionManager.getDefaultSubscriptionId(), appType, authType, hexChallenge);
    724     }
    725 
    726     @Rpc(description = "Get Authentication Challenge Response from a " +
    727             "given SIM Application for a specified Subscription")
    728     public String telephonyGetIccSimChallengeResponseForSubscription(
    729             @RpcParameter(name = "subId") Integer subId,
    730             @RpcParameter(name = "appType") Integer appType,
    731             @RpcParameter(name = "authType") Integer authType,
    732             @RpcParameter(name = "hexChallenge") String hexChallenge) {
    733 
    734         try {
    735             String b64Data = BaseEncoding.base64().encode(BaseEncoding.base16().decode(hexChallenge));
    736             String b64Result = mTelephonyManager.getIccAuthentication(subId, appType, authType, b64Data);
    737             return (b64Result != null)
    738                     ? BaseEncoding.base16().encode(BaseEncoding.base64().decode(b64Result)) : null;
    739         } catch(Exception e) {
    740             Log.e("Exception in phoneGetIccSimChallengeResponseForSubscription" + e.toString());
    741             return null;
    742         }
    743     }
    744 
    745     @Rpc(description = "Returns the unique subscriber ID (such as IMSI) " +
    746             "for default subscription ID, or null if unavailable")
    747     public String telephonyGetSubscriberId() {
    748         return telephonyGetSubscriberIdForSubscription(
    749                 SubscriptionManager.getDefaultSubscriptionId());
    750     }
    751 
    752     @Rpc(description = "Returns the unique subscriber ID (such as IMSI) " +
    753                        "for specified subscription ID, or null if unavailable")
    754     public String telephonyGetSubscriberIdForSubscription(
    755                   @RpcParameter(name = "subId") Integer subId) {
    756         return mTelephonyManager.getSubscriberId(subId);
    757     }
    758 
    759     @Rpc(description = "Retrieves the alphabetic id associated with the" +
    760                        " voice mail number for default subscription ID.")
    761     public String telephonyGetVoiceMailAlphaTag() {
    762         return telephonyGetVoiceMailAlphaTagForSubscription(
    763                    SubscriptionManager.getDefaultSubscriptionId());
    764     }
    765 
    766 
    767     @Rpc(description = "Retrieves the alphabetic id associated with the " +
    768                        "voice mail number for specified subscription ID.")
    769     public String telephonyGetVoiceMailAlphaTagForSubscription(
    770                   @RpcParameter(name = "subId") Integer subId) {
    771         return mTelephonyManager.getVoiceMailAlphaTag(subId);
    772     }
    773 
    774     @Rpc(description = "Returns the voice mail number " +
    775                        "for default subscription ID; null if unavailable.")
    776     public String telephonyGetVoiceMailNumber() {
    777         return telephonyGetVoiceMailNumberForSubscription(
    778                    SubscriptionManager.getDefaultSubscriptionId());
    779     }
    780 
    781     @Rpc(description = "Returns the voice mail number " +
    782                         "for specified subscription ID; null if unavailable.")
    783     public String telephonyGetVoiceMailNumberForSubscription(
    784                   @RpcParameter(name = "subId") Integer subId) {
    785         return mTelephonyManager.getVoiceMailNumber(subId);
    786     }
    787 
    788     @Rpc(description = "Get voice message count for specified subscription ID.")
    789     public Integer telephonyGetVoiceMailCountForSubscription(
    790                    @RpcParameter(name = "subId") Integer subId) {
    791         return mTelephonyManager.getVoiceMessageCount(subId);
    792     }
    793 
    794     @Rpc(description = "Get voice message count for default subscription ID.")
    795     public Integer telephonyGetVoiceMailCount() {
    796         return mTelephonyManager.getVoiceMessageCount();
    797     }
    798 
    799     @Rpc(description = "Returns true if the device is in  roaming state" +
    800                        "for default subscription ID")
    801     public Boolean telephonyCheckNetworkRoaming() {
    802         return telephonyCheckNetworkRoamingForSubscription(
    803                              SubscriptionManager.getDefaultSubscriptionId());
    804     }
    805 
    806     @Rpc(description = "Returns true if the device is in roaming state " +
    807                        "for specified subscription ID")
    808     public Boolean telephonyCheckNetworkRoamingForSubscription(
    809                    @RpcParameter(name = "subId") Integer subId) {
    810         return mTelephonyManager.isNetworkRoaming(subId);
    811     }
    812 
    813     @Rpc(description = "Returns the unique device ID such as MEID or IMEI " +
    814                        "for deault sim slot ID, null if unavailable")
    815     public String telephonyGetDeviceId() {
    816         return telephonyGetDeviceIdForSlotId(mTelephonyManager.getDefaultSim());
    817     }
    818 
    819     @Rpc(description = "Returns the unique device ID such as MEID or IMEI for" +
    820                        " specified slot ID, null if unavailable")
    821     public String telephonyGetDeviceIdForSlotId(
    822                   @RpcParameter(name = "slotId")
    823                   Integer slotId){
    824         return mTelephonyManager.getDeviceId(slotId);
    825     }
    826 
    827     @Rpc(description = "Returns the modem sw version, such as IMEI-SV;" +
    828                        " null if unavailable")
    829     public String telephonyGetDeviceSoftwareVersion() {
    830         return mTelephonyManager.getDeviceSoftwareVersion();
    831     }
    832 
    833     @Rpc(description = "Returns phone # string \"line 1\", such as MSISDN " +
    834                        "for default subscription ID; null if unavailable")
    835     public String telephonyGetLine1Number() {
    836         return mTelephonyManager.getLine1Number();
    837     }
    838 
    839     @Rpc(description = "Returns phone # string \"line 1\", such as MSISDN " +
    840                        "for specified subscription ID; null if unavailable")
    841     public String telephonyGetLine1NumberForSubscription(
    842                   @RpcParameter(name = "subId") Integer subId) {
    843         return mTelephonyManager.getLine1Number(subId);
    844     }
    845 
    846     @Rpc(description = "Returns the Alpha Tag for the default subscription " +
    847                        "ID; null if unavailable")
    848     public String telephonyGetLine1AlphaTag() {
    849         return mTelephonyManager.getLine1AlphaTag();
    850     }
    851 
    852     @Rpc(description = "Returns the Alpha Tag for the specified subscription " +
    853                        "ID; null if unavailable")
    854     public String telephonyGetLine1AlphaTagForSubscription(
    855                   @RpcParameter(name = "subId") Integer subId) {
    856         return mTelephonyManager.getLine1AlphaTag(subId);
    857     }
    858 
    859     @Rpc(description = "Set the Line1-number (phone number) and Alpha Tag" +
    860                        "for the default subscription")
    861     public Boolean telephonySetLine1Number(
    862                 @RpcParameter(name = "number") String number,
    863                 @RpcOptional
    864                 @RpcParameter(name = "alphaTag") String alphaTag) {
    865         return mTelephonyManager.setLine1NumberForDisplay(alphaTag, number);
    866     }
    867 
    868     @Rpc(description = "Set the Line1-number (phone number) and Alpha Tag" +
    869                        "for the specified subscription")
    870     public Boolean telephonySetLine1NumberForSubscription(
    871                 @RpcParameter(name = "subId") Integer subId,
    872                 @RpcParameter(name = "number") String number,
    873                 @RpcOptional
    874                 @RpcParameter(name = "alphaTag") String alphaTag) {
    875         return mTelephonyManager.setLine1NumberForDisplay(subId, alphaTag, number);
    876     }
    877 
    878     @Rpc(description = "Returns the neighboring cell information of the device.")
    879     public List<NeighboringCellInfo> telephonyGetNeighboringCellInfo() {
    880         return mTelephonyManager.getNeighboringCellInfo();
    881     }
    882 
    883     @Rpc(description =  "Sets the minimum reporting interval for CellInfo" +
    884                         "0-as quickly as possible, 0x7FFFFFF-off")
    885     public void telephonySetCellInfoListRate(
    886                 @RpcParameter(name = "rate") Integer rate
    887             ) {
    888         mTelephonyManager.setCellInfoListRate(rate);
    889     }
    890 
    891     @Rpc(description = "Returns all observed cell information from all radios"+
    892                        "on the device including the primary and neighboring cells")
    893     public List<CellInfo> telephonyGetAllCellInfo() {
    894         return mTelephonyManager.getAllCellInfo();
    895     }
    896 
    897     @Rpc(description = "Returns True if cellular data is enabled for" +
    898                        "default data subscription ID.")
    899     public Boolean telephonyIsDataEnabled() {
    900         return telephonyIsDataEnabledForSubscription(
    901                    SubscriptionManager.getDefaultDataSubscriptionId());
    902     }
    903 
    904     @Rpc(description = "Returns True if data connection is enabled.")
    905     public Boolean telephonyIsDataEnabledForSubscription(
    906                    @RpcParameter(name = "subId") Integer subId) {
    907         return mTelephonyManager.getDataEnabled(subId);
    908     }
    909 
    910     @Rpc(description = "Toggles data connection on /off for" +
    911                        " default data subscription ID.")
    912     public void telephonyToggleDataConnection(
    913                 @RpcParameter(name = "enabled")
    914                 @RpcOptional Boolean enabled) {
    915         telephonyToggleDataConnectionForSubscription(
    916                          SubscriptionManager.getDefaultDataSubscriptionId(), enabled);
    917     }
    918 
    919     @Rpc(description = "Toggles data connection on/off for" +
    920                        " specified subscription ID")
    921     public void telephonyToggleDataConnectionForSubscription(
    922                 @RpcParameter(name = "subId") Integer subId,
    923                 @RpcParameter(name = "enabled")
    924                 @RpcOptional Boolean enabled) {
    925         if (enabled == null) {
    926             enabled = !telephonyIsDataEnabledForSubscription(subId);
    927         }
    928         mTelephonyManager.setDataEnabled(subId, enabled);
    929     }
    930 
    931     @Rpc(description = "Sets an APN and make that as preferred APN.")
    932     public void telephonySetAPN(@RpcParameter(name = "name") final String name,
    933                        @RpcParameter(name = "apn") final String apn,
    934                        @RpcParameter(name = "type") @RpcOptional @RpcDefault("")
    935                        final String type,
    936                        @RpcParameter(name = "subId") @RpcOptional Integer subId) {
    937         //TODO: b/26273471 Need to find out how to set APN for specific subId
    938         Uri uri;
    939         Cursor cursor;
    940 
    941         String mcc = "";
    942         String mnc = "";
    943 
    944         String numeric = SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
    945         // MCC is first 3 chars and then in 2 - 3 chars of MNC
    946         if (numeric != null && numeric.length() > 4) {
    947             // Country code
    948             mcc = numeric.substring(0, 3);
    949             // Network code
    950             mnc = numeric.substring(3);
    951         }
    952 
    953         uri = mService.getContentResolver().insert(
    954                 Telephony.Carriers.CONTENT_URI, new ContentValues());
    955         if (uri == null) {
    956             Log.w("Failed to insert new provider into " + Telephony.Carriers.CONTENT_URI);
    957             return;
    958         }
    959 
    960         cursor = mService.getContentResolver().query(uri, sProjection, null, null, null);
    961         cursor.moveToFirst();
    962 
    963         ContentValues values = new ContentValues();
    964 
    965         values.put(Telephony.Carriers.NAME, name);
    966         values.put(Telephony.Carriers.APN, apn);
    967         values.put(Telephony.Carriers.PROXY, "");
    968         values.put(Telephony.Carriers.PORT, "");
    969         values.put(Telephony.Carriers.MMSPROXY, "");
    970         values.put(Telephony.Carriers.MMSPORT, "");
    971         values.put(Telephony.Carriers.USER, "");
    972         values.put(Telephony.Carriers.SERVER, "");
    973         values.put(Telephony.Carriers.PASSWORD, "");
    974         values.put(Telephony.Carriers.MMSC, "");
    975         values.put(Telephony.Carriers.TYPE, type);
    976         values.put(Telephony.Carriers.MCC, mcc);
    977         values.put(Telephony.Carriers.MNC, mnc);
    978         values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
    979 
    980         int ret = mService.getContentResolver().update(uri, values, null, null);
    981         Log.d("after update " + ret);
    982         cursor.close();
    983 
    984         // Make this APN as the preferred
    985         String where = "name=\"" + name + "\"";
    986 
    987         Cursor c = mService.getContentResolver().query(
    988                 Telephony.Carriers.CONTENT_URI,
    989                 new String[] {
    990                         "_id", "name", "apn", "type"
    991                 }, where, null,
    992                 Telephony.Carriers.DEFAULT_SORT_ORDER);
    993         if (c != null) {
    994             c.moveToFirst();
    995             String key = c.getString(0);
    996             final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn";
    997             ContentResolver resolver = mService.getContentResolver();
    998             ContentValues prefAPN = new ContentValues();
    999             prefAPN.put("apn_id", key);
   1000             resolver.update(Uri.parse(PREFERRED_APN_URI), prefAPN, null, null);
   1001         }
   1002         c.close();
   1003     }
   1004 
   1005     @Rpc(description = "Returns the number of APNs defined")
   1006     public int telephonyGetNumberOfAPNs(
   1007                @RpcParameter(name = "subId")
   1008                @RpcOptional Integer subId) {
   1009         //TODO: b/26273471 Need to find out how to get Number of APNs for specific subId
   1010         int result = 0;
   1011         String where = "numeric=\"" + android.os.SystemProperties.get(
   1012                         TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "") + "\"";
   1013 
   1014         Cursor cursor = mService.getContentResolver().query(
   1015                 Telephony.Carriers.CONTENT_URI,
   1016                 new String[] {"_id", "name", "apn", "type"}, where, null,
   1017                 Telephony.Carriers.DEFAULT_SORT_ORDER);
   1018 
   1019         if (cursor != null) {
   1020             result = cursor.getCount();
   1021         }
   1022         cursor.close();
   1023         return result;
   1024     }
   1025 
   1026     @Rpc(description = "Returns the currently selected APN name")
   1027     public String telephonyGetSelectedAPN(
   1028                   @RpcParameter(name = "subId")
   1029                   @RpcOptional Integer subId) {
   1030         //TODO: b/26273471 Need to find out how to get selected APN for specific subId
   1031         String key = null;
   1032         int ID_INDEX = 0;
   1033         final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn";
   1034 
   1035         Cursor cursor = mService.getContentResolver().query(Uri.parse(PREFERRED_APN_URI),
   1036                 new String[] {"name"}, null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
   1037 
   1038         if (cursor.getCount() > 0) {
   1039             cursor.moveToFirst();
   1040             key = cursor.getString(ID_INDEX);
   1041         }
   1042         cursor.close();
   1043         return key;
   1044     }
   1045 
   1046     @Rpc(description = "Returns the current data connection state")
   1047     public String telephonyGetDataConnectionState() {
   1048         return TelephonyUtils.getDataConnectionStateString(
   1049             mTelephonyManager.getDataState());
   1050     }
   1051 
   1052     @Rpc(description = "Enables or Disables Video Calling()")
   1053     public void telephonyEnableVideoCalling(boolean enable) {
   1054         mTelephonyManager.enableVideoCalling(enable);
   1055     }
   1056 
   1057     @Rpc(description = "Returns a boolean of whether or not " +
   1058             "video calling setting is enabled by the user")
   1059     public Boolean telephonyIsVideoCallingEnabled() {
   1060         return mTelephonyManager.isVideoCallingEnabled();
   1061     }
   1062 
   1063     @Rpc(description = "Returns a boolean of whether video calling is available for use")
   1064     public Boolean telephonyIsVideoCallingAvailable() {
   1065         return mTelephonyManager.isVideoTelephonyAvailable();
   1066     }
   1067 
   1068     @Rpc(description = "Returns a boolean of whether or not the device is ims registered")
   1069     public Boolean telephonyIsImsRegistered() {
   1070         return mTelephonyManager.isImsRegistered();
   1071     }
   1072 
   1073     @Rpc(description = "Returns a boolean of whether or not volte calling is available for use")
   1074     public Boolean telephonyIsVolteAvailable() {
   1075         return mTelephonyManager.isVolteAvailable();
   1076     }
   1077 
   1078     @Rpc(description = "Returns a boolean of whether or not wifi calling is available for use")
   1079     public Boolean telephonyIsWifiCallingAvailable() {
   1080         return mTelephonyManager.isWifiCallingAvailable();
   1081     }
   1082 
   1083     @Rpc(description = "Returns the service state for default subscription ID")
   1084     public String telephonyGetServiceState() {
   1085         //TODO: b/26273807 need to have framework API to get service state.
   1086         return telephonyGetServiceStateForSubscription(
   1087                                  SubscriptionManager.getDefaultSubscriptionId());
   1088     }
   1089 
   1090     @Rpc(description = "Returns the service state for specified subscription ID")
   1091     public String telephonyGetServiceStateForSubscription(
   1092                   @RpcParameter(name = "subId") Integer subId) {
   1093         //TODO: b/26273807 need to have framework API to get service state.
   1094         return null;
   1095     }
   1096 
   1097     @Rpc(description = "Returns the call state for default subscription ID")
   1098     public String telephonyGetCallState() {
   1099         return telephonyGetCallStateForSubscription(
   1100                                SubscriptionManager.getDefaultSubscriptionId());
   1101     }
   1102 
   1103     @Rpc(description = "Returns the call state for specified subscription ID")
   1104     public String telephonyGetCallStateForSubscription(
   1105                   @RpcParameter(name = "subId") Integer subId) {
   1106         return TelephonyUtils.getTelephonyCallStateString(
   1107             mTelephonyManager.getCallState(subId));
   1108     }
   1109 
   1110     @Rpc(description = "Returns current signal strength for default subscription ID.")
   1111     public SignalStrength telephonyGetSignalStrength() {
   1112         return telephonyGetSignalStrengthForSubscription(
   1113                                SubscriptionManager.getDefaultSubscriptionId());
   1114     }
   1115 
   1116     @Rpc(description = "Returns current signal strength for specified subscription ID.")
   1117     public SignalStrength telephonyGetSignalStrengthForSubscription(
   1118                     @RpcParameter(name = "subId") Integer subId) {
   1119         StateChangeListener listener = getStateChangeListenerForSubscription(subId, false);
   1120         if(listener == null) {
   1121             Log.e("Invalid subscription ID");
   1122             return null;
   1123         }
   1124         return listener.mSignalStrengthChangeListener.mSignalStrengths;
   1125     }
   1126 
   1127     @Rpc(description = "Returns the sim count.")
   1128     public int telephonyGetSimCount() {
   1129         return mTelephonyManager.getSimCount();
   1130     }
   1131 
   1132     private StateChangeListener getStateChangeListenerForSubscription(
   1133             int subId,
   1134             boolean createIfNeeded) {
   1135 
   1136        if(mStateChangeListeners.get(subId) == null) {
   1137             if(createIfNeeded == false) {
   1138                 return null;
   1139             }
   1140 
   1141             if(mSubscriptionManager.getActiveSubscriptionInfo(subId) == null) {
   1142                 Log.e("Cannot get listener for invalid/inactive subId");
   1143                 return null;
   1144             }
   1145 
   1146             mStateChangeListeners.put(subId, new StateChangeListener(subId));
   1147         }
   1148 
   1149         return mStateChangeListeners.get(subId);
   1150     }
   1151 
   1152     //FIXME: This whole class needs reworking. Why do we have separate listeners for everything?
   1153     //We need one listener that overrides multiple methods.
   1154     private final class StateChangeListener {
   1155         public ServiceStateChangeListener mServiceStateChangeListener;
   1156         public SignalStrengthChangeListener mSignalStrengthChangeListener;
   1157         public CallStateChangeListener mCallStateChangeListener;
   1158         public CellInfoChangeListener mCellInfoChangeListener;
   1159         public DataConnectionStateChangeListener mDataConnectionStateChangeListener;
   1160         public DataConnectionRealTimeInfoChangeListener mDataConnectionRTInfoChangeListener;
   1161         public VoiceMailStateChangeListener mVoiceMailStateChangeListener;
   1162 
   1163         public StateChangeListener(int subId) {
   1164             mServiceStateChangeListener =
   1165                 new ServiceStateChangeListener(mEventFacade, subId, mService.getMainLooper());
   1166             mSignalStrengthChangeListener =
   1167                 new SignalStrengthChangeListener(mEventFacade, subId, mService.getMainLooper());
   1168             mDataConnectionStateChangeListener =
   1169                 new DataConnectionStateChangeListener(
   1170                         mEventFacade, mTelephonyManager, subId, mService.getMainLooper());
   1171             mCallStateChangeListener =
   1172                 new CallStateChangeListener(mEventFacade, subId, mService.getMainLooper());
   1173             mCellInfoChangeListener =
   1174                 new CellInfoChangeListener(mEventFacade, subId, mService.getMainLooper());
   1175             mDataConnectionRTInfoChangeListener =
   1176                 new DataConnectionRealTimeInfoChangeListener(
   1177                         mEventFacade, subId, mService.getMainLooper());
   1178             mVoiceMailStateChangeListener =
   1179                 new VoiceMailStateChangeListener(mEventFacade, subId, mService.getMainLooper());
   1180         }
   1181 
   1182         public void shutdown() {
   1183             mTelephonyManager.listen(
   1184                     mServiceStateChangeListener,
   1185                     PhoneStateListener.LISTEN_NONE);
   1186             mTelephonyManager.listen(
   1187                     mSignalStrengthChangeListener,
   1188                     PhoneStateListener.LISTEN_NONE);
   1189             mTelephonyManager.listen(
   1190                     mCallStateChangeListener,
   1191                     PhoneStateListener.LISTEN_NONE);
   1192             mTelephonyManager.listen(
   1193                     mCellInfoChangeListener,
   1194                     PhoneStateListener.LISTEN_NONE);
   1195             mTelephonyManager.listen(
   1196                     mDataConnectionStateChangeListener,
   1197                     PhoneStateListener.LISTEN_NONE);
   1198             mTelephonyManager.listen(
   1199                     mDataConnectionRTInfoChangeListener,
   1200                     PhoneStateListener.LISTEN_NONE);
   1201             mTelephonyManager.listen(
   1202                     mVoiceMailStateChangeListener,
   1203                     PhoneStateListener.LISTEN_NONE);
   1204         }
   1205 
   1206         protected void finalize() {
   1207             try {
   1208                 shutdown();
   1209             } catch(Exception e) {}
   1210         }
   1211     }
   1212 
   1213     @Override
   1214     public void shutdown() {
   1215         for(StateChangeListener listener : mStateChangeListeners.values()) {
   1216             listener.shutdown();
   1217         }
   1218     }
   1219 }
   1220