TelephonyManager.java revision ca3597d4369b308c7c4d3553abfcc5788d10414a
1/*
2 * Copyright (C) 2008 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
17package android.telephony;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.content.Context;
22import android.os.Bundle;
23import android.os.RemoteException;
24import android.os.ServiceManager;
25import android.os.SystemProperties;
26import android.telephony.Rlog;
27
28import com.android.internal.telephony.IPhoneSubInfo;
29import com.android.internal.telephony.ITelephony;
30import com.android.internal.telephony.ITelephonyRegistry;
31import com.android.internal.telephony.PhoneConstants;
32import com.android.internal.telephony.RILConstants;
33import com.android.internal.telephony.TelephonyProperties;
34
35import java.io.FileInputStream;
36import java.io.IOException;
37import java.util.List;
38import java.util.regex.Matcher;
39import java.util.regex.Pattern;
40
41/**
42 * Provides access to information about the telephony services on
43 * the device. Applications can use the methods in this class to
44 * determine telephony services and states, as well as to access some
45 * types of subscriber information. Applications can also register
46 * a listener to receive notification of telephony state changes.
47 * <p>
48 * You do not instantiate this class directly; instead, you retrieve
49 * a reference to an instance through
50 * {@link android.content.Context#getSystemService
51 * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
52 * <p>
53 * Note that access to some telephony information is
54 * permission-protected. Your application cannot access the protected
55 * information unless it has the appropriate permissions declared in
56 * its manifest file. Where permissions apply, they are noted in the
57 * the methods through which you access the protected information.
58 */
59public class TelephonyManager {
60    private static final String TAG = "TelephonyManager";
61
62    private static ITelephonyRegistry sRegistry;
63    private final Context mContext;
64
65    /** @hide */
66    public TelephonyManager(Context context) {
67        Context appContext = context.getApplicationContext();
68        if (appContext != null) {
69            mContext = appContext;
70        } else {
71            mContext = context;
72        }
73
74        if (sRegistry == null) {
75            sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
76                    "telephony.registry"));
77        }
78    }
79
80    /** @hide */
81    private TelephonyManager() {
82        mContext = null;
83    }
84
85    private static TelephonyManager sInstance = new TelephonyManager();
86
87    /** @hide
88    /* @deprecated - use getSystemService as described above */
89    public static TelephonyManager getDefault() {
90        return sInstance;
91    }
92
93    /** {@hide} */
94    public static TelephonyManager from(Context context) {
95        return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
96    }
97
98    //
99    // Broadcast Intent actions
100    //
101
102    /**
103     * Broadcast intent action indicating that the call state (cellular)
104     * on the device has changed.
105     *
106     * <p>
107     * The {@link #EXTRA_STATE} extra indicates the new call state.
108     * If the new state is RINGING, a second extra
109     * {@link #EXTRA_INCOMING_NUMBER} provides the incoming phone number as
110     * a String.
111     *
112     * <p class="note">
113     * Requires the READ_PHONE_STATE permission.
114     *
115     * <p class="note">
116     * This was a {@link android.content.Context#sendStickyBroadcast sticky}
117     * broadcast in version 1.0, but it is no longer sticky.
118     * Instead, use {@link #getCallState} to synchronously query the current call state.
119     *
120     * @see #EXTRA_STATE
121     * @see #EXTRA_INCOMING_NUMBER
122     * @see #getCallState
123     */
124    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
125    public static final String ACTION_PHONE_STATE_CHANGED =
126            "android.intent.action.PHONE_STATE";
127
128    /**
129     * The Phone app sends this intent when a user opts to respond-via-message during an incoming
130     * call. By default, the MMS app consumes this message and sends a text message to the caller. A
131     * third party app can provide this functionality in lieu of MMS app by consuming this Intent
132     * and sending the message using their own messaging system.  The intent contains a URI
133     * describing the recipient, and an EXTRA containg the message itself.
134     * <p>
135     * The intent-filter which consumes this Intent needs to be in a service which requires the
136     * permission SEND_RESPOND_VIA_MESSAGE.
137     *
138     * <p>
139     * {@link android.content.Intent#getData} is a URI describing the recipient of the message.
140     * <p>
141     * The {@link android.content.Intent#EXTRA_TEXT} extra contains the message
142     * to send.
143     * <p>
144     * Output: nothing.
145     */
146    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
147    public static final String ACTION_RESPOND_VIA_MESSAGE =
148            "android.intent.action.RESPOND_VIA_MESSAGE";
149
150    /**
151     * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
152     * for a String containing the new call state.
153     *
154     * @see #EXTRA_STATE_IDLE
155     * @see #EXTRA_STATE_RINGING
156     * @see #EXTRA_STATE_OFFHOOK
157     *
158     * <p class="note">
159     * Retrieve with
160     * {@link android.content.Intent#getStringExtra(String)}.
161     */
162    public static final String EXTRA_STATE = PhoneConstants.STATE_KEY;
163
164    /**
165     * Value used with {@link #EXTRA_STATE} corresponding to
166     * {@link #CALL_STATE_IDLE}.
167     */
168    public static final String EXTRA_STATE_IDLE = PhoneConstants.State.IDLE.toString();
169
170    /**
171     * Value used with {@link #EXTRA_STATE} corresponding to
172     * {@link #CALL_STATE_RINGING}.
173     */
174    public static final String EXTRA_STATE_RINGING = PhoneConstants.State.RINGING.toString();
175
176    /**
177     * Value used with {@link #EXTRA_STATE} corresponding to
178     * {@link #CALL_STATE_OFFHOOK}.
179     */
180    public static final String EXTRA_STATE_OFFHOOK = PhoneConstants.State.OFFHOOK.toString();
181
182    /**
183     * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
184     * for a String containing the incoming phone number.
185     * Only valid when the new call state is RINGING.
186     *
187     * <p class="note">
188     * Retrieve with
189     * {@link android.content.Intent#getStringExtra(String)}.
190     */
191    public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
192
193
194    //
195    //
196    // Device Info
197    //
198    //
199
200    /**
201     * Returns the software version number for the device, for example,
202     * the IMEI/SV for GSM phones. Return null if the software version is
203     * not available.
204     *
205     * <p>Requires Permission:
206     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
207     */
208    public String getDeviceSoftwareVersion() {
209        try {
210            return getSubscriberInfo().getDeviceSvn();
211        } catch (RemoteException ex) {
212            return null;
213        } catch (NullPointerException ex) {
214            return null;
215        }
216    }
217
218    /**
219     * Returns the unique device ID, for example, the IMEI for GSM and the MEID
220     * or ESN for CDMA phones. Return null if device ID is not available.
221     *
222     * <p>Requires Permission:
223     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
224     */
225    public String getDeviceId() {
226        try {
227            return getSubscriberInfo().getDeviceId();
228        } catch (RemoteException ex) {
229            return null;
230        } catch (NullPointerException ex) {
231            return null;
232        }
233    }
234
235    /**
236     * Returns the current location of the device.
237     *<p>
238     * If there is only one radio in the device and that radio has an LTE connection,
239     * this method will return null. The implementation must not to try add LTE
240     * identifiers into the existing cdma/gsm classes.
241     *<p>
242     * In the future this call will be deprecated.
243     *<p>
244     * @return Current location of the device or null if not available.
245     *
246     * <p>Requires Permission:
247     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
248     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.
249     */
250    public CellLocation getCellLocation() {
251        try {
252            Bundle bundle = getITelephony().getCellLocation();
253            if (bundle.isEmpty()) return null;
254            CellLocation cl = CellLocation.newFromBundle(bundle);
255            if (cl.isEmpty())
256                return null;
257            return cl;
258        } catch (RemoteException ex) {
259            return null;
260        } catch (NullPointerException ex) {
261            return null;
262        }
263    }
264
265    /**
266     * Enables location update notifications.  {@link PhoneStateListener#onCellLocationChanged
267     * PhoneStateListener.onCellLocationChanged} will be called on location updates.
268     *
269     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
270     * CONTROL_LOCATION_UPDATES}
271     *
272     * @hide
273     */
274    public void enableLocationUpdates() {
275        try {
276            getITelephony().enableLocationUpdates();
277        } catch (RemoteException ex) {
278        } catch (NullPointerException ex) {
279        }
280    }
281
282    /**
283     * Disables location update notifications.  {@link PhoneStateListener#onCellLocationChanged
284     * PhoneStateListener.onCellLocationChanged} will be called on location updates.
285     *
286     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
287     * CONTROL_LOCATION_UPDATES}
288     *
289     * @hide
290     */
291    public void disableLocationUpdates() {
292        try {
293            getITelephony().disableLocationUpdates();
294        } catch (RemoteException ex) {
295        } catch (NullPointerException ex) {
296        }
297    }
298
299    /**
300     * Returns the neighboring cell information of the device. The getAllCellInfo is preferred
301     * and use this only if getAllCellInfo return nulls or an empty list.
302     *<p>
303     * In the future this call will be deprecated.
304     *<p>
305     * @return List of NeighboringCellInfo or null if info unavailable.
306     *
307     * <p>Requires Permission:
308     * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
309     */
310    public List<NeighboringCellInfo> getNeighboringCellInfo() {
311        try {
312            return getITelephony().getNeighboringCellInfo(mContext.getBasePackageName());
313        } catch (RemoteException ex) {
314            return null;
315        } catch (NullPointerException ex) {
316            return null;
317        }
318    }
319
320    /** No phone radio. */
321    public static final int PHONE_TYPE_NONE = PhoneConstants.PHONE_TYPE_NONE;
322    /** Phone radio is GSM. */
323    public static final int PHONE_TYPE_GSM = PhoneConstants.PHONE_TYPE_GSM;
324    /** Phone radio is CDMA. */
325    public static final int PHONE_TYPE_CDMA = PhoneConstants.PHONE_TYPE_CDMA;
326    /** Phone is via SIP. */
327    public static final int PHONE_TYPE_SIP = PhoneConstants.PHONE_TYPE_SIP;
328
329    /**
330     * Returns the current phone type.
331     * TODO: This is a last minute change and hence hidden.
332     *
333     * @see #PHONE_TYPE_NONE
334     * @see #PHONE_TYPE_GSM
335     * @see #PHONE_TYPE_CDMA
336     * @see #PHONE_TYPE_SIP
337     *
338     * {@hide}
339     */
340    public int getCurrentPhoneType() {
341        try{
342            ITelephony telephony = getITelephony();
343            if (telephony != null) {
344                return telephony.getActivePhoneType();
345            } else {
346                // This can happen when the ITelephony interface is not up yet.
347                return getPhoneTypeFromProperty();
348            }
349        } catch (RemoteException ex) {
350            // This shouldn't happen in the normal case, as a backup we
351            // read from the system property.
352            return getPhoneTypeFromProperty();
353        } catch (NullPointerException ex) {
354            // This shouldn't happen in the normal case, as a backup we
355            // read from the system property.
356            return getPhoneTypeFromProperty();
357        }
358    }
359
360    /**
361     * Returns a constant indicating the device phone type.  This
362     * indicates the type of radio used to transmit voice calls.
363     *
364     * @see #PHONE_TYPE_NONE
365     * @see #PHONE_TYPE_GSM
366     * @see #PHONE_TYPE_CDMA
367     * @see #PHONE_TYPE_SIP
368     */
369    public int getPhoneType() {
370        if (!isVoiceCapable()) {
371            return PHONE_TYPE_NONE;
372        }
373        return getCurrentPhoneType();
374    }
375
376    private int getPhoneTypeFromProperty() {
377        int type =
378            SystemProperties.getInt(TelephonyProperties.CURRENT_ACTIVE_PHONE,
379                    getPhoneTypeFromNetworkType());
380        return type;
381    }
382
383    private int getPhoneTypeFromNetworkType() {
384        // When the system property CURRENT_ACTIVE_PHONE, has not been set,
385        // use the system property for default network type.
386        // This is a fail safe, and can only happen at first boot.
387        int mode = SystemProperties.getInt("ro.telephony.default_network", -1);
388        if (mode == -1)
389            return PHONE_TYPE_NONE;
390        return getPhoneType(mode);
391    }
392
393    /**
394     * This function returns the type of the phone, depending
395     * on the network mode.
396     *
397     * @param networkMode
398     * @return Phone Type
399     *
400     * @hide
401     */
402    public static int getPhoneType(int networkMode) {
403        switch(networkMode) {
404        case RILConstants.NETWORK_MODE_CDMA:
405        case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
406        case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
407            return PhoneConstants.PHONE_TYPE_CDMA;
408
409        case RILConstants.NETWORK_MODE_WCDMA_PREF:
410        case RILConstants.NETWORK_MODE_GSM_ONLY:
411        case RILConstants.NETWORK_MODE_WCDMA_ONLY:
412        case RILConstants.NETWORK_MODE_GSM_UMTS:
413        case RILConstants.NETWORK_MODE_LTE_GSM_WCDMA:
414        case RILConstants.NETWORK_MODE_LTE_WCDMA:
415            return PhoneConstants.PHONE_TYPE_GSM;
416
417        // Use CDMA Phone for the global mode including CDMA
418        case RILConstants.NETWORK_MODE_GLOBAL:
419        case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:
420        case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA:
421            return PhoneConstants.PHONE_TYPE_CDMA;
422
423        case RILConstants.NETWORK_MODE_LTE_ONLY:
424            if (getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
425                return PhoneConstants.PHONE_TYPE_CDMA;
426            } else {
427                return PhoneConstants.PHONE_TYPE_GSM;
428            }
429        default:
430            return PhoneConstants.PHONE_TYPE_GSM;
431        }
432    }
433
434    /**
435     * The contents of the /proc/cmdline file
436     */
437    private static String getProcCmdLine()
438    {
439        String cmdline = "";
440        FileInputStream is = null;
441        try {
442            is = new FileInputStream("/proc/cmdline");
443            byte [] buffer = new byte[2048];
444            int count = is.read(buffer);
445            if (count > 0) {
446                cmdline = new String(buffer, 0, count);
447            }
448        } catch (IOException e) {
449            Rlog.d(TAG, "No /proc/cmdline exception=" + e);
450        } finally {
451            if (is != null) {
452                try {
453                    is.close();
454                } catch (IOException e) {
455                }
456            }
457        }
458        Rlog.d(TAG, "/proc/cmdline=" + cmdline);
459        return cmdline;
460    }
461
462    /** Kernel command line */
463    private static final String sKernelCmdLine = getProcCmdLine();
464
465    /** Pattern for selecting the product type from the kernel command line */
466    private static final Pattern sProductTypePattern =
467        Pattern.compile("\\sproduct_type\\s*=\\s*(\\w+)");
468
469    /** The ProductType used for LTE on CDMA devices */
470    private static final String sLteOnCdmaProductType =
471        SystemProperties.get(TelephonyProperties.PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE, "");
472
473    /**
474     * Return if the current radio is LTE on CDMA. This
475     * is a tri-state return value as for a period of time
476     * the mode may be unknown.
477     *
478     * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
479     * or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
480     *
481     * @hide
482     */
483    public static int getLteOnCdmaModeStatic() {
484        int retVal;
485        int curVal;
486        String productType = "";
487
488        curVal = SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE,
489                    PhoneConstants.LTE_ON_CDMA_UNKNOWN);
490        retVal = curVal;
491        if (retVal == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {
492            Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);
493            if (matcher.find()) {
494                productType = matcher.group(1);
495                if (sLteOnCdmaProductType.equals(productType)) {
496                    retVal = PhoneConstants.LTE_ON_CDMA_TRUE;
497                } else {
498                    retVal = PhoneConstants.LTE_ON_CDMA_FALSE;
499                }
500            } else {
501                retVal = PhoneConstants.LTE_ON_CDMA_FALSE;
502            }
503        }
504
505        Rlog.d(TAG, "getLteOnCdmaMode=" + retVal + " curVal=" + curVal +
506                " product_type='" + productType +
507                "' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'");
508        return retVal;
509    }
510
511    //
512    //
513    // Current Network
514    //
515    //
516
517    /**
518     * Returns the alphabetic name of current registered operator.
519     * <p>
520     * Availability: Only when user is registered to a network. Result may be
521     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
522     * on a CDMA network).
523     */
524    public String getNetworkOperatorName() {
525        return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA);
526    }
527
528    /**
529     * Returns the numeric name (MCC+MNC) of current registered operator.
530     * <p>
531     * Availability: Only when user is registered to a network. Result may be
532     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
533     * on a CDMA network).
534     */
535    public String getNetworkOperator() {
536        return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
537    }
538
539    /**
540     * Returns true if the device is considered roaming on the current
541     * network, for GSM purposes.
542     * <p>
543     * Availability: Only when user registered to a network.
544     */
545    public boolean isNetworkRoaming() {
546        return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
547    }
548
549    /**
550     * Returns the ISO country code equivalent of the current registered
551     * operator's MCC (Mobile Country Code).
552     * <p>
553     * Availability: Only when user is registered to a network. Result may be
554     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
555     * on a CDMA network).
556     */
557    public String getNetworkCountryIso() {
558        return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);
559    }
560
561    /** Network type is unknown */
562    public static final int NETWORK_TYPE_UNKNOWN = 0;
563    /** Current network is GPRS */
564    public static final int NETWORK_TYPE_GPRS = 1;
565    /** Current network is EDGE */
566    public static final int NETWORK_TYPE_EDGE = 2;
567    /** Current network is UMTS */
568    public static final int NETWORK_TYPE_UMTS = 3;
569    /** Current network is CDMA: Either IS95A or IS95B*/
570    public static final int NETWORK_TYPE_CDMA = 4;
571    /** Current network is EVDO revision 0*/
572    public static final int NETWORK_TYPE_EVDO_0 = 5;
573    /** Current network is EVDO revision A*/
574    public static final int NETWORK_TYPE_EVDO_A = 6;
575    /** Current network is 1xRTT*/
576    public static final int NETWORK_TYPE_1xRTT = 7;
577    /** Current network is HSDPA */
578    public static final int NETWORK_TYPE_HSDPA = 8;
579    /** Current network is HSUPA */
580    public static final int NETWORK_TYPE_HSUPA = 9;
581    /** Current network is HSPA */
582    public static final int NETWORK_TYPE_HSPA = 10;
583    /** Current network is iDen */
584    public static final int NETWORK_TYPE_IDEN = 11;
585    /** Current network is EVDO revision B*/
586    public static final int NETWORK_TYPE_EVDO_B = 12;
587    /** Current network is LTE */
588    public static final int NETWORK_TYPE_LTE = 13;
589    /** Current network is eHRPD */
590    public static final int NETWORK_TYPE_EHRPD = 14;
591    /** Current network is HSPA+ */
592    public static final int NETWORK_TYPE_HSPAP = 15;
593
594    /**
595     * @return the NETWORK_TYPE_xxxx for current data connection.
596     */
597    public int getNetworkType() {
598        return getDataNetworkType();
599    }
600
601    /**
602     * Returns a constant indicating the radio technology (network type)
603     * currently in use on the device for data transmission.
604     * @return the network type
605     *
606     * @see #NETWORK_TYPE_UNKNOWN
607     * @see #NETWORK_TYPE_GPRS
608     * @see #NETWORK_TYPE_EDGE
609     * @see #NETWORK_TYPE_UMTS
610     * @see #NETWORK_TYPE_HSDPA
611     * @see #NETWORK_TYPE_HSUPA
612     * @see #NETWORK_TYPE_HSPA
613     * @see #NETWORK_TYPE_CDMA
614     * @see #NETWORK_TYPE_EVDO_0
615     * @see #NETWORK_TYPE_EVDO_A
616     * @see #NETWORK_TYPE_EVDO_B
617     * @see #NETWORK_TYPE_1xRTT
618     * @see #NETWORK_TYPE_IDEN
619     * @see #NETWORK_TYPE_LTE
620     * @see #NETWORK_TYPE_EHRPD
621     * @see #NETWORK_TYPE_HSPAP
622     *
623     * @hide
624     */
625    public int getDataNetworkType() {
626        try{
627            ITelephony telephony = getITelephony();
628            if (telephony != null) {
629                return telephony.getDataNetworkType();
630            } else {
631                // This can happen when the ITelephony interface is not up yet.
632                return NETWORK_TYPE_UNKNOWN;
633            }
634        } catch(RemoteException ex) {
635            // This shouldn't happen in the normal case
636            return NETWORK_TYPE_UNKNOWN;
637        } catch (NullPointerException ex) {
638            // This could happen before phone restarts due to crashing
639            return NETWORK_TYPE_UNKNOWN;
640        }
641    }
642
643    /**
644     * Returns the NETWORK_TYPE_xxxx for voice
645     *
646     * @hide
647     */
648    public int getVoiceNetworkType() {
649        try{
650            ITelephony telephony = getITelephony();
651            if (telephony != null) {
652                return telephony.getVoiceNetworkType();
653            } else {
654                // This can happen when the ITelephony interface is not up yet.
655                return NETWORK_TYPE_UNKNOWN;
656            }
657        } catch(RemoteException ex) {
658            // This shouldn't happen in the normal case
659            return NETWORK_TYPE_UNKNOWN;
660        } catch (NullPointerException ex) {
661            // This could happen before phone restarts due to crashing
662            return NETWORK_TYPE_UNKNOWN;
663        }
664    }
665
666    /** Unknown network class. {@hide} */
667    public static final int NETWORK_CLASS_UNKNOWN = 0;
668    /** Class of broadly defined "2G" networks. {@hide} */
669    public static final int NETWORK_CLASS_2_G = 1;
670    /** Class of broadly defined "3G" networks. {@hide} */
671    public static final int NETWORK_CLASS_3_G = 2;
672    /** Class of broadly defined "4G" networks. {@hide} */
673    public static final int NETWORK_CLASS_4_G = 3;
674
675    /**
676     * Return general class of network type, such as "3G" or "4G". In cases
677     * where classification is contentious, this method is conservative.
678     *
679     * @hide
680     */
681    public static int getNetworkClass(int networkType) {
682        switch (networkType) {
683            case NETWORK_TYPE_GPRS:
684            case NETWORK_TYPE_EDGE:
685            case NETWORK_TYPE_CDMA:
686            case NETWORK_TYPE_1xRTT:
687            case NETWORK_TYPE_IDEN:
688                return NETWORK_CLASS_2_G;
689            case NETWORK_TYPE_UMTS:
690            case NETWORK_TYPE_EVDO_0:
691            case NETWORK_TYPE_EVDO_A:
692            case NETWORK_TYPE_HSDPA:
693            case NETWORK_TYPE_HSUPA:
694            case NETWORK_TYPE_HSPA:
695            case NETWORK_TYPE_EVDO_B:
696            case NETWORK_TYPE_EHRPD:
697            case NETWORK_TYPE_HSPAP:
698                return NETWORK_CLASS_3_G;
699            case NETWORK_TYPE_LTE:
700                return NETWORK_CLASS_4_G;
701            default:
702                return NETWORK_CLASS_UNKNOWN;
703        }
704    }
705
706    /**
707     * Returns a string representation of the radio technology (network type)
708     * currently in use on the device.
709     * @return the name of the radio technology
710     *
711     * @hide pending API council review
712     */
713    public String getNetworkTypeName() {
714        return getNetworkTypeName(getNetworkType());
715    }
716
717    /** {@hide} */
718    public static String getNetworkTypeName(int type) {
719        switch (type) {
720            case NETWORK_TYPE_GPRS:
721                return "GPRS";
722            case NETWORK_TYPE_EDGE:
723                return "EDGE";
724            case NETWORK_TYPE_UMTS:
725                return "UMTS";
726            case NETWORK_TYPE_HSDPA:
727                return "HSDPA";
728            case NETWORK_TYPE_HSUPA:
729                return "HSUPA";
730            case NETWORK_TYPE_HSPA:
731                return "HSPA";
732            case NETWORK_TYPE_CDMA:
733                return "CDMA";
734            case NETWORK_TYPE_EVDO_0:
735                return "CDMA - EvDo rev. 0";
736            case NETWORK_TYPE_EVDO_A:
737                return "CDMA - EvDo rev. A";
738            case NETWORK_TYPE_EVDO_B:
739                return "CDMA - EvDo rev. B";
740            case NETWORK_TYPE_1xRTT:
741                return "CDMA - 1xRTT";
742            case NETWORK_TYPE_LTE:
743                return "LTE";
744            case NETWORK_TYPE_EHRPD:
745                return "CDMA - eHRPD";
746            case NETWORK_TYPE_IDEN:
747                return "iDEN";
748            case NETWORK_TYPE_HSPAP:
749                return "HSPA+";
750            default:
751                return "UNKNOWN";
752        }
753    }
754
755    //
756    //
757    // SIM Card
758    //
759    //
760
761    /** SIM card state: Unknown. Signifies that the SIM is in transition
762     *  between states. For example, when the user inputs the SIM pin
763     *  under PIN_REQUIRED state, a query for sim status returns
764     *  this state before turning to SIM_STATE_READY. */
765    public static final int SIM_STATE_UNKNOWN = 0;
766    /** SIM card state: no SIM card is available in the device */
767    public static final int SIM_STATE_ABSENT = 1;
768    /** SIM card state: Locked: requires the user's SIM PIN to unlock */
769    public static final int SIM_STATE_PIN_REQUIRED = 2;
770    /** SIM card state: Locked: requires the user's SIM PUK to unlock */
771    public static final int SIM_STATE_PUK_REQUIRED = 3;
772    /** SIM card state: Locked: requries a network PIN to unlock */
773    public static final int SIM_STATE_NETWORK_LOCKED = 4;
774    /** SIM card state: Ready */
775    public static final int SIM_STATE_READY = 5;
776
777    /**
778     * @return true if a ICC card is present
779     */
780    public boolean hasIccCard() {
781        try {
782            return getITelephony().hasIccCard();
783        } catch (RemoteException ex) {
784            // Assume no ICC card if remote exception which shouldn't happen
785            return false;
786        } catch (NullPointerException ex) {
787            // This could happen before phone restarts due to crashing
788            return false;
789        }
790    }
791
792    /**
793     * Returns a constant indicating the state of the
794     * device SIM card.
795     *
796     * @see #SIM_STATE_UNKNOWN
797     * @see #SIM_STATE_ABSENT
798     * @see #SIM_STATE_PIN_REQUIRED
799     * @see #SIM_STATE_PUK_REQUIRED
800     * @see #SIM_STATE_NETWORK_LOCKED
801     * @see #SIM_STATE_READY
802     */
803    public int getSimState() {
804        String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE);
805        if ("ABSENT".equals(prop)) {
806            return SIM_STATE_ABSENT;
807        }
808        else if ("PIN_REQUIRED".equals(prop)) {
809            return SIM_STATE_PIN_REQUIRED;
810        }
811        else if ("PUK_REQUIRED".equals(prop)) {
812            return SIM_STATE_PUK_REQUIRED;
813        }
814        else if ("NETWORK_LOCKED".equals(prop)) {
815            return SIM_STATE_NETWORK_LOCKED;
816        }
817        else if ("READY".equals(prop)) {
818            return SIM_STATE_READY;
819        }
820        else {
821            return SIM_STATE_UNKNOWN;
822        }
823    }
824
825    /**
826     * Returns the MCC+MNC (mobile country code + mobile network code) of the
827     * provider of the SIM. 5 or 6 decimal digits.
828     * <p>
829     * Availability: SIM state must be {@link #SIM_STATE_READY}
830     *
831     * @see #getSimState
832     */
833    public String getSimOperator() {
834        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
835    }
836
837    /**
838     * Returns the Service Provider Name (SPN).
839     * <p>
840     * Availability: SIM state must be {@link #SIM_STATE_READY}
841     *
842     * @see #getSimState
843     */
844    public String getSimOperatorName() {
845        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA);
846    }
847
848    /**
849     * Returns the ISO country code equivalent for the SIM provider's country code.
850     */
851    public String getSimCountryIso() {
852        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY);
853    }
854
855    /**
856     * Returns the serial number of the SIM, if applicable. Return null if it is
857     * unavailable.
858     * <p>
859     * Requires Permission:
860     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
861     */
862    public String getSimSerialNumber() {
863        try {
864            return getSubscriberInfo().getIccSerialNumber();
865        } catch (RemoteException ex) {
866            return null;
867        } catch (NullPointerException ex) {
868            // This could happen before phone restarts due to crashing
869            return null;
870        }
871    }
872
873    /**
874     * Return if the current radio is LTE on CDMA. This
875     * is a tri-state return value as for a period of time
876     * the mode may be unknown.
877     *
878     * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
879     * or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
880     *
881     * @hide
882     */
883    public int getLteOnCdmaMode() {
884        try {
885            return getITelephony().getLteOnCdmaMode();
886        } catch (RemoteException ex) {
887            // Assume no ICC card if remote exception which shouldn't happen
888            return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
889        } catch (NullPointerException ex) {
890            // This could happen before phone restarts due to crashing
891            return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
892        }
893    }
894
895    //
896    //
897    // Subscriber Info
898    //
899    //
900
901    /**
902     * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
903     * Return null if it is unavailable.
904     * <p>
905     * Requires Permission:
906     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
907     */
908    public String getSubscriberId() {
909        try {
910            return getSubscriberInfo().getSubscriberId();
911        } catch (RemoteException ex) {
912            return null;
913        } catch (NullPointerException ex) {
914            // This could happen before phone restarts due to crashing
915            return null;
916        }
917    }
918
919    /**
920     * Returns the Group Identifier Level1 for a GSM phone.
921     * Return null if it is unavailable.
922     * <p>
923     * Requires Permission:
924     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
925     */
926    public String getGroupIdLevel1() {
927        try {
928            return getSubscriberInfo().getGroupIdLevel1();
929        } catch (RemoteException ex) {
930            return null;
931        } catch (NullPointerException ex) {
932            // This could happen before phone restarts due to crashing
933            return null;
934        }
935    }
936
937    /**
938     * Returns the phone number string for line 1, for example, the MSISDN
939     * for a GSM phone. Return null if it is unavailable.
940     * <p>
941     * Requires Permission:
942     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
943     */
944    public String getLine1Number() {
945        try {
946            return getSubscriberInfo().getLine1Number();
947        } catch (RemoteException ex) {
948            return null;
949        } catch (NullPointerException ex) {
950            // This could happen before phone restarts due to crashing
951            return null;
952        }
953    }
954
955    /**
956     * Returns the alphabetic identifier associated with the line 1 number.
957     * Return null if it is unavailable.
958     * <p>
959     * Requires Permission:
960     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
961     * @hide
962     * nobody seems to call this.
963     */
964    public String getLine1AlphaTag() {
965        try {
966            return getSubscriberInfo().getLine1AlphaTag();
967        } catch (RemoteException ex) {
968            return null;
969        } catch (NullPointerException ex) {
970            // This could happen before phone restarts due to crashing
971            return null;
972        }
973    }
974
975    /**
976     * Returns the MSISDN string.
977     * for a GSM phone. Return null if it is unavailable.
978     * <p>
979     * Requires Permission:
980     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
981     *
982     * @hide
983     */
984    public String getMsisdn() {
985        try {
986            return getSubscriberInfo().getMsisdn();
987        } catch (RemoteException ex) {
988            return null;
989        } catch (NullPointerException ex) {
990            // This could happen before phone restarts due to crashing
991            return null;
992        }
993    }
994
995    /**
996     * Returns the voice mail number. Return null if it is unavailable.
997     * <p>
998     * Requires Permission:
999     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1000     */
1001    public String getVoiceMailNumber() {
1002        try {
1003            return getSubscriberInfo().getVoiceMailNumber();
1004        } catch (RemoteException ex) {
1005            return null;
1006        } catch (NullPointerException ex) {
1007            // This could happen before phone restarts due to crashing
1008            return null;
1009        }
1010    }
1011
1012    /**
1013     * Returns the complete voice mail number. Return null if it is unavailable.
1014     * <p>
1015     * Requires Permission:
1016     *   {@link android.Manifest.permission#CALL_PRIVILEGED CALL_PRIVILEGED}
1017     *
1018     * @hide
1019     */
1020    public String getCompleteVoiceMailNumber() {
1021        try {
1022            return getSubscriberInfo().getCompleteVoiceMailNumber();
1023        } catch (RemoteException ex) {
1024            return null;
1025        } catch (NullPointerException ex) {
1026            // This could happen before phone restarts due to crashing
1027            return null;
1028        }
1029    }
1030
1031    /**
1032     * Returns the voice mail count. Return 0 if unavailable.
1033     * <p>
1034     * Requires Permission:
1035     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1036     * @hide
1037     */
1038    public int getVoiceMessageCount() {
1039        try {
1040            return getITelephony().getVoiceMessageCount();
1041        } catch (RemoteException ex) {
1042            return 0;
1043        } catch (NullPointerException ex) {
1044            // This could happen before phone restarts due to crashing
1045            return 0;
1046        }
1047    }
1048
1049    /**
1050     * Retrieves the alphabetic identifier associated with the voice
1051     * mail number.
1052     * <p>
1053     * Requires Permission:
1054     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
1055     */
1056    public String getVoiceMailAlphaTag() {
1057        try {
1058            return getSubscriberInfo().getVoiceMailAlphaTag();
1059        } catch (RemoteException ex) {
1060            return null;
1061        } catch (NullPointerException ex) {
1062            // This could happen before phone restarts due to crashing
1063            return null;
1064        }
1065    }
1066
1067    /**
1068     * Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
1069     * @return the IMPI, or null if not present or not loaded
1070     * @hide
1071     */
1072    public String getIsimImpi() {
1073        try {
1074            return getSubscriberInfo().getIsimImpi();
1075        } catch (RemoteException ex) {
1076            return null;
1077        } catch (NullPointerException ex) {
1078            // This could happen before phone restarts due to crashing
1079            return null;
1080        }
1081    }
1082
1083    /**
1084     * Returns the IMS home network domain name that was loaded from the ISIM.
1085     * @return the IMS domain name, or null if not present or not loaded
1086     * @hide
1087     */
1088    public String getIsimDomain() {
1089        try {
1090            return getSubscriberInfo().getIsimDomain();
1091        } catch (RemoteException ex) {
1092            return null;
1093        } catch (NullPointerException ex) {
1094            // This could happen before phone restarts due to crashing
1095            return null;
1096        }
1097    }
1098
1099    /**
1100     * Returns the IMS public user identities (IMPU) that were loaded from the ISIM.
1101     * @return an array of IMPU strings, with one IMPU per string, or null if
1102     *      not present or not loaded
1103     * @hide
1104     */
1105    public String[] getIsimImpu() {
1106        try {
1107            return getSubscriberInfo().getIsimImpu();
1108        } catch (RemoteException ex) {
1109            return null;
1110        } catch (NullPointerException ex) {
1111            // This could happen before phone restarts due to crashing
1112            return null;
1113        }
1114    }
1115
1116    private IPhoneSubInfo getSubscriberInfo() {
1117        // get it each time because that process crashes a lot
1118        return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
1119    }
1120
1121
1122    /** Device call state: No activity. */
1123    public static final int CALL_STATE_IDLE = 0;
1124    /** Device call state: Ringing. A new call arrived and is
1125     *  ringing or waiting. In the latter case, another call is
1126     *  already active. */
1127    public static final int CALL_STATE_RINGING = 1;
1128    /** Device call state: Off-hook. At least one call exists
1129      * that is dialing, active, or on hold, and no calls are ringing
1130      * or waiting. */
1131    public static final int CALL_STATE_OFFHOOK = 2;
1132
1133    /**
1134     * Returns a constant indicating the call state (cellular) on the device.
1135     */
1136    public int getCallState() {
1137        try {
1138            return getITelephony().getCallState();
1139        } catch (RemoteException ex) {
1140            // the phone process is restarting.
1141            return CALL_STATE_IDLE;
1142        } catch (NullPointerException ex) {
1143          // the phone process is restarting.
1144          return CALL_STATE_IDLE;
1145      }
1146    }
1147
1148    /** Data connection activity: No traffic. */
1149    public static final int DATA_ACTIVITY_NONE = 0x00000000;
1150    /** Data connection activity: Currently receiving IP PPP traffic. */
1151    public static final int DATA_ACTIVITY_IN = 0x00000001;
1152    /** Data connection activity: Currently sending IP PPP traffic. */
1153    public static final int DATA_ACTIVITY_OUT = 0x00000002;
1154    /** Data connection activity: Currently both sending and receiving
1155     *  IP PPP traffic. */
1156    public static final int DATA_ACTIVITY_INOUT = DATA_ACTIVITY_IN | DATA_ACTIVITY_OUT;
1157    /**
1158     * Data connection is active, but physical link is down
1159     */
1160    public static final int DATA_ACTIVITY_DORMANT = 0x00000004;
1161
1162    /**
1163     * Returns a constant indicating the type of activity on a data connection
1164     * (cellular).
1165     *
1166     * @see #DATA_ACTIVITY_NONE
1167     * @see #DATA_ACTIVITY_IN
1168     * @see #DATA_ACTIVITY_OUT
1169     * @see #DATA_ACTIVITY_INOUT
1170     * @see #DATA_ACTIVITY_DORMANT
1171     */
1172    public int getDataActivity() {
1173        try {
1174            return getITelephony().getDataActivity();
1175        } catch (RemoteException ex) {
1176            // the phone process is restarting.
1177            return DATA_ACTIVITY_NONE;
1178        } catch (NullPointerException ex) {
1179          // the phone process is restarting.
1180          return DATA_ACTIVITY_NONE;
1181      }
1182    }
1183
1184    /** Data connection state: Unknown.  Used before we know the state.
1185     * @hide
1186     */
1187    public static final int DATA_UNKNOWN        = -1;
1188    /** Data connection state: Disconnected. IP traffic not available. */
1189    public static final int DATA_DISCONNECTED   = 0;
1190    /** Data connection state: Currently setting up a data connection. */
1191    public static final int DATA_CONNECTING     = 1;
1192    /** Data connection state: Connected. IP traffic should be available. */
1193    public static final int DATA_CONNECTED      = 2;
1194    /** Data connection state: Suspended. The connection is up, but IP
1195     * traffic is temporarily unavailable. For example, in a 2G network,
1196     * data activity may be suspended when a voice call arrives. */
1197    public static final int DATA_SUSPENDED      = 3;
1198
1199    /**
1200     * Returns a constant indicating the current data connection state
1201     * (cellular).
1202     *
1203     * @see #DATA_DISCONNECTED
1204     * @see #DATA_CONNECTING
1205     * @see #DATA_CONNECTED
1206     * @see #DATA_SUSPENDED
1207     */
1208    public int getDataState() {
1209        try {
1210            return getITelephony().getDataState();
1211        } catch (RemoteException ex) {
1212            // the phone process is restarting.
1213            return DATA_DISCONNECTED;
1214        } catch (NullPointerException ex) {
1215            return DATA_DISCONNECTED;
1216        }
1217    }
1218
1219    private ITelephony getITelephony() {
1220        return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
1221    }
1222
1223    //
1224    //
1225    // PhoneStateListener
1226    //
1227    //
1228
1229    /**
1230     * Registers a listener object to receive notification of changes
1231     * in specified telephony states.
1232     * <p>
1233     * To register a listener, pass a {@link PhoneStateListener}
1234     * and specify at least one telephony state of interest in
1235     * the events argument.
1236     *
1237     * At registration, and when a specified telephony state
1238     * changes, the telephony manager invokes the appropriate
1239     * callback method on the listener object and passes the
1240     * current (udpated) values.
1241     * <p>
1242     * To unregister a listener, pass the listener object and set the
1243     * events argument to
1244     * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
1245     *
1246     * @param listener The {@link PhoneStateListener} object to register
1247     *                 (or unregister)
1248     * @param events The telephony state(s) of interest to the listener,
1249     *               as a bitwise-OR combination of {@link PhoneStateListener}
1250     *               LISTEN_ flags.
1251     */
1252    public void listen(PhoneStateListener listener, int events) {
1253        String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
1254        try {
1255            Boolean notifyNow = (getITelephony() != null);
1256            sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
1257        } catch (RemoteException ex) {
1258            // system process dead
1259        } catch (NullPointerException ex) {
1260            // system process dead
1261        }
1262    }
1263
1264    /**
1265     * Returns the CDMA ERI icon index to display
1266     *
1267     * @hide
1268     */
1269    public int getCdmaEriIconIndex() {
1270        try {
1271            return getITelephony().getCdmaEriIconIndex();
1272        } catch (RemoteException ex) {
1273            // the phone process is restarting.
1274            return -1;
1275        } catch (NullPointerException ex) {
1276            return -1;
1277        }
1278    }
1279
1280    /**
1281     * Returns the CDMA ERI icon mode,
1282     * 0 - ON
1283     * 1 - FLASHING
1284     *
1285     * @hide
1286     */
1287    public int getCdmaEriIconMode() {
1288        try {
1289            return getITelephony().getCdmaEriIconMode();
1290        } catch (RemoteException ex) {
1291            // the phone process is restarting.
1292            return -1;
1293        } catch (NullPointerException ex) {
1294            return -1;
1295        }
1296    }
1297
1298    /**
1299     * Returns the CDMA ERI text,
1300     *
1301     * @hide
1302     */
1303    public String getCdmaEriText() {
1304        try {
1305            return getITelephony().getCdmaEriText();
1306        } catch (RemoteException ex) {
1307            // the phone process is restarting.
1308            return null;
1309        } catch (NullPointerException ex) {
1310            return null;
1311        }
1312    }
1313
1314    /**
1315     * @return true if the current device is "voice capable".
1316     * <p>
1317     * "Voice capable" means that this device supports circuit-switched
1318     * (i.e. voice) phone calls over the telephony network, and is allowed
1319     * to display the in-call UI while a cellular voice call is active.
1320     * This will be false on "data only" devices which can't make voice
1321     * calls and don't support any in-call UI.
1322     * <p>
1323     * Note: the meaning of this flag is subtly different from the
1324     * PackageManager.FEATURE_TELEPHONY system feature, which is available
1325     * on any device with a telephony radio, even if the device is
1326     * data-only.
1327     *
1328     * @hide pending API review
1329     */
1330    public boolean isVoiceCapable() {
1331        if (mContext == null) return true;
1332        return mContext.getResources().getBoolean(
1333                com.android.internal.R.bool.config_voice_capable);
1334    }
1335
1336    /**
1337     * @return true if the current device supports sms service.
1338     * <p>
1339     * If true, this means that the device supports both sending and
1340     * receiving sms via the telephony network.
1341     * <p>
1342     * Note: Voicemail waiting sms, cell broadcasting sms, and MMS are
1343     *       disabled when device doesn't support sms.
1344     *
1345     * @hide pending API review
1346     */
1347    public boolean isSmsCapable() {
1348        if (mContext == null) return true;
1349        return mContext.getResources().getBoolean(
1350                com.android.internal.R.bool.config_sms_capable);
1351    }
1352
1353    /**
1354     * Returns all observed cell information from all radios on the
1355     * device including the primary and neighboring cells. This does
1356     * not cause or change the rate of PhoneStateListner#onCellInfoChanged.
1357     *<p>
1358     * The list can include one or more of {@link android.telephony.CellInfoGsm CellInfoGsm},
1359     * {@link android.telephony.CellInfoCdma CellInfoCdma},
1360     * {@link android.telephony.CellInfoLte CellInfoLte} and
1361     * {@link android.telephony.CellInfoWcdma CellInfoCdma} in any combination.
1362     * Specifically on devices with multiple radios it is typical to see instances of
1363     * one or more of any these in the list. In addition 0, 1 or more CellInfo
1364     * objects may return isRegistered() true.
1365     *<p>
1366     * This is preferred over using getCellLocation although for older
1367     * devices this may return null in which case getCellLocation should
1368     * be called.
1369     *<p>
1370     * @return List of CellInfo or null if info unavailable.
1371     *
1372     * <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
1373     */
1374    public List<CellInfo> getAllCellInfo() {
1375        try {
1376            return getITelephony().getAllCellInfo();
1377        } catch (RemoteException ex) {
1378            return null;
1379        } catch (NullPointerException ex) {
1380            return null;
1381        }
1382    }
1383
1384    /**
1385     * Sets the minimum time in milli-seconds between {@link PhoneStateListener#onCellInfoChanged
1386     * PhoneStateListener.onCellInfoChanged} will be invoked.
1387     *<p>
1388     * The default, 0, means invoke onCellInfoChanged when any of the reported
1389     * information changes. Setting the value to INT_MAX(0x7fffffff) means never issue
1390     * A onCellInfoChanged.
1391     *<p>
1392     * @param rateInMillis the rate
1393     *
1394     * @hide
1395     */
1396    public void setCellInfoListRate(int rateInMillis) {
1397        try {
1398            getITelephony().setCellInfoListRate(rateInMillis);
1399        } catch (RemoteException ex) {
1400        } catch (NullPointerException ex) {
1401        }
1402    }
1403}
1404