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