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