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