Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.telephony;
     18 
     19 import android.os.Bundle;
     20 import android.os.Parcel;
     21 import android.os.Parcelable;
     22 import android.util.Log;
     23 
     24 /**
     25  * Contains phone state and service related information.
     26  *
     27  * The following phone information is included in returned ServiceState:
     28  *
     29  * <ul>
     30  *   <li>Service state: IN_SERVICE, OUT_OF_SERVICE, EMERGENCY_ONLY, POWER_OFF
     31  *   <li>Roaming indicator
     32  *   <li>Operator name, short name and numeric id
     33  *   <li>Network selection mode
     34  * </ul>
     35  */
     36 public class ServiceState implements Parcelable {
     37 
     38     static final String LOG_TAG = "PHONE";
     39 
     40     /**
     41      * Normal operation condition, the phone is registered
     42      * with an operator either in home network or in roaming.
     43      */
     44     public static final int STATE_IN_SERVICE = 0;
     45 
     46     /**
     47      * Phone is not registered with any operator, the phone
     48      * can be currently searching a new operator to register to, or not
     49      * searching to registration at all, or registration is denied, or radio
     50      * signal is not available.
     51      */
     52     public static final int STATE_OUT_OF_SERVICE = 1;
     53 
     54     /**
     55      * The phone is registered and locked.  Only emergency numbers are allowed. {@more}
     56      */
     57     public static final int STATE_EMERGENCY_ONLY = 2;
     58 
     59     /**
     60      * Radio of telephony is explicitly powered off.
     61      */
     62     public static final int STATE_POWER_OFF = 3;
     63 
     64 
     65     /**
     66      * Available radio technologies for GSM, UMTS and CDMA.
     67      */
     68     /** @hide */
     69     public static final int RADIO_TECHNOLOGY_UNKNOWN = 0;
     70     /** @hide */
     71     public static final int RADIO_TECHNOLOGY_GPRS = 1;
     72     /** @hide */
     73     public static final int RADIO_TECHNOLOGY_EDGE = 2;
     74     /** @hide */
     75     public static final int RADIO_TECHNOLOGY_UMTS = 3;
     76     /** @hide */
     77     public static final int RADIO_TECHNOLOGY_IS95A = 4;
     78     /** @hide */
     79     public static final int RADIO_TECHNOLOGY_IS95B = 5;
     80     /** @hide */
     81     public static final int RADIO_TECHNOLOGY_1xRTT = 6;
     82     /** @hide */
     83     public static final int RADIO_TECHNOLOGY_EVDO_0 = 7;
     84     /** @hide */
     85     public static final int RADIO_TECHNOLOGY_EVDO_A = 8;
     86     /** @hide */
     87     public static final int RADIO_TECHNOLOGY_HSDPA = 9;
     88     /** @hide */
     89     public static final int RADIO_TECHNOLOGY_HSUPA = 10;
     90     /** @hide */
     91     public static final int RADIO_TECHNOLOGY_HSPA = 11;
     92     /** @hide */
     93     public static final int RADIO_TECHNOLOGY_EVDO_B = 12;
     94 
     95     /**
     96      * Available registration states for GSM, UMTS and CDMA.
     97      */
     98     /** @hide */
     99     public static final int REGISTRATION_STATE_NOT_REGISTERED_AND_NOT_SEARCHING = 0;
    100     /** @hide */
    101     public static final int REGISTRATION_STATE_HOME_NETWORK = 1;
    102     /** @hide */
    103     public static final int REGISTRATION_STATE_NOT_REGISTERED_AND_SEARCHING = 2;
    104     /** @hide */
    105     public static final int REGISTRATION_STATE_REGISTRATION_DENIED = 3;
    106     /** @hide */
    107     public static final int REGISTRATION_STATE_UNKNOWN = 4;
    108     /** @hide */
    109     public static final int REGISTRATION_STATE_ROAMING = 5;
    110 
    111     private int mState = STATE_OUT_OF_SERVICE;
    112     private boolean mRoaming;
    113     private String mOperatorAlphaLong;
    114     private String mOperatorAlphaShort;
    115     private String mOperatorNumeric;
    116     private boolean mIsManualNetworkSelection;
    117 
    118     private boolean mIsEmergencyOnly;
    119 
    120     //***** CDMA
    121     private int mRadioTechnology;
    122     private boolean mCssIndicator;
    123     private int mNetworkId;
    124     private int mSystemId;
    125     private int mCdmaRoamingIndicator;
    126     private int mCdmaDefaultRoamingIndicator;
    127     private int mCdmaEriIconIndex;
    128     private int mCdmaEriIconMode;
    129 
    130     /**
    131      * Create a new ServiceState from a intent notifier Bundle
    132      *
    133      * This method is used by PhoneStateIntentReceiver and maybe by
    134      * external applications.
    135      *
    136      * @param m Bundle from intent notifier
    137      * @return newly created ServiceState
    138      * @hide
    139      */
    140     public static ServiceState newFromBundle(Bundle m) {
    141         ServiceState ret;
    142         ret = new ServiceState();
    143         ret.setFromNotifierBundle(m);
    144         return ret;
    145     }
    146 
    147     /**
    148      * Empty constructor
    149      */
    150     public ServiceState() {
    151     }
    152 
    153     /**
    154      * Copy constructors
    155      *
    156      * @param s Source service state
    157      */
    158     public ServiceState(ServiceState s) {
    159         copyFrom(s);
    160     }
    161 
    162     protected void copyFrom(ServiceState s) {
    163         mState = s.mState;
    164         mRoaming = s.mRoaming;
    165         mOperatorAlphaLong = s.mOperatorAlphaLong;
    166         mOperatorAlphaShort = s.mOperatorAlphaShort;
    167         mOperatorNumeric = s.mOperatorNumeric;
    168         mIsManualNetworkSelection = s.mIsManualNetworkSelection;
    169         mRadioTechnology = s.mRadioTechnology;
    170         mCssIndicator = s.mCssIndicator;
    171         mNetworkId = s.mNetworkId;
    172         mSystemId = s.mSystemId;
    173         mCdmaRoamingIndicator = s.mCdmaRoamingIndicator;
    174         mCdmaDefaultRoamingIndicator = s.mCdmaDefaultRoamingIndicator;
    175         mCdmaEriIconIndex = s.mCdmaEriIconIndex;
    176         mCdmaEriIconMode = s.mCdmaEriIconMode;
    177         mIsEmergencyOnly = s.mIsEmergencyOnly;
    178     }
    179 
    180     /**
    181      * Construct a ServiceState object from the given parcel.
    182      */
    183     public ServiceState(Parcel in) {
    184         mState = in.readInt();
    185         mRoaming = in.readInt() != 0;
    186         mOperatorAlphaLong = in.readString();
    187         mOperatorAlphaShort = in.readString();
    188         mOperatorNumeric = in.readString();
    189         mIsManualNetworkSelection = in.readInt() != 0;
    190         mRadioTechnology = in.readInt();
    191         mCssIndicator = (in.readInt() != 0);
    192         mNetworkId = in.readInt();
    193         mSystemId = in.readInt();
    194         mCdmaRoamingIndicator = in.readInt();
    195         mCdmaDefaultRoamingIndicator = in.readInt();
    196         mCdmaEriIconIndex = in.readInt();
    197         mCdmaEriIconMode = in.readInt();
    198         mIsEmergencyOnly = in.readInt() != 0;
    199     }
    200 
    201     public void writeToParcel(Parcel out, int flags) {
    202         out.writeInt(mState);
    203         out.writeInt(mRoaming ? 1 : 0);
    204         out.writeString(mOperatorAlphaLong);
    205         out.writeString(mOperatorAlphaShort);
    206         out.writeString(mOperatorNumeric);
    207         out.writeInt(mIsManualNetworkSelection ? 1 : 0);
    208         out.writeInt(mRadioTechnology);
    209         out.writeInt(mCssIndicator ? 1 : 0);
    210         out.writeInt(mNetworkId);
    211         out.writeInt(mSystemId);
    212         out.writeInt(mCdmaRoamingIndicator);
    213         out.writeInt(mCdmaDefaultRoamingIndicator);
    214         out.writeInt(mCdmaEriIconIndex);
    215         out.writeInt(mCdmaEriIconMode);
    216         out.writeInt(mIsEmergencyOnly ? 1 : 0);
    217     }
    218 
    219     public int describeContents() {
    220         return 0;
    221     }
    222 
    223     public static final Parcelable.Creator<ServiceState> CREATOR =
    224             new Parcelable.Creator<ServiceState>() {
    225         public ServiceState createFromParcel(Parcel in) {
    226             return new ServiceState(in);
    227         }
    228 
    229         public ServiceState[] newArray(int size) {
    230             return new ServiceState[size];
    231         }
    232     };
    233 
    234     /**
    235      * Get current service state of phone
    236      *
    237      * @see #STATE_IN_SERVICE
    238      * @see #STATE_OUT_OF_SERVICE
    239      * @see #STATE_EMERGENCY_ONLY
    240      * @see #STATE_POWER_OFF
    241      */
    242     public int getState() {
    243         return mState;
    244     }
    245 
    246     /**
    247      * Get current roaming indicator of phone
    248      * (note: not just decoding from TS 27.007 7.2)
    249      *
    250      * @return true if TS 27.007 7.2 roaming is true
    251      *              and ONS is different from SPN
    252      *
    253      */
    254     public boolean getRoaming() {
    255         return mRoaming;
    256     }
    257 
    258     /**
    259      * @hide
    260      */
    261     public boolean isEmergencyOnly() {
    262         return mIsEmergencyOnly;
    263     }
    264 
    265     /**
    266      * @hide
    267      */
    268     public int getCdmaRoamingIndicator(){
    269         return this.mCdmaRoamingIndicator;
    270     }
    271 
    272     /**
    273      * @hide
    274      */
    275     public int getCdmaDefaultRoamingIndicator(){
    276         return this.mCdmaDefaultRoamingIndicator;
    277     }
    278 
    279     /**
    280      * @hide
    281      */
    282     public int getCdmaEriIconIndex() {
    283         return this.mCdmaEriIconIndex;
    284     }
    285 
    286     /**
    287      * @hide
    288      */
    289     public int getCdmaEriIconMode() {
    290         return this.mCdmaEriIconMode;
    291     }
    292 
    293     /**
    294      * Get current registered operator name in long alphanumeric format.
    295      *
    296      * In GSM/UMTS, long format can be up to 16 characters long.
    297      * In CDMA, returns the ERI text, if set. Otherwise, returns the ONS.
    298      *
    299      * @return long name of operator, null if unregistered or unknown
    300      */
    301     public String getOperatorAlphaLong() {
    302         return mOperatorAlphaLong;
    303     }
    304 
    305     /**
    306      * Get current registered operator name in short alphanumeric format.
    307      *
    308      * In GSM/UMTS, short format can be up to 8 characters long.
    309      *
    310      * @return short name of operator, null if unregistered or unknown
    311      */
    312     public String getOperatorAlphaShort() {
    313         return mOperatorAlphaShort;
    314     }
    315 
    316     /**
    317      * Get current registered operator numeric id.
    318      *
    319      * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit
    320      * network code.
    321      *
    322      * @return numeric format of operator, null if unregistered or unknown
    323      */
    324     /*
    325      * The country code can be decoded using
    326      * {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}.
    327      */
    328     public String getOperatorNumeric() {
    329         return mOperatorNumeric;
    330     }
    331 
    332     /**
    333      * Get current network selection mode.
    334      *
    335      * @return true if manual mode, false if automatic mode
    336      */
    337     public boolean getIsManualSelection() {
    338         return mIsManualNetworkSelection;
    339     }
    340 
    341     @Override
    342     public int hashCode() {
    343         return ((mState * 0x1234)
    344                 + (mRoaming ? 1 : 0)
    345                 + (mIsManualNetworkSelection ? 1 : 0)
    346                 + ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode())
    347                 + ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
    348                 + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
    349                 + mCdmaRoamingIndicator
    350                 + mCdmaDefaultRoamingIndicator
    351                 + (mIsEmergencyOnly ? 1 : 0));
    352     }
    353 
    354     @Override
    355     public boolean equals (Object o) {
    356         ServiceState s;
    357 
    358         try {
    359             s = (ServiceState) o;
    360         } catch (ClassCastException ex) {
    361             return false;
    362         }
    363 
    364         if (o == null) {
    365             return false;
    366         }
    367 
    368         return (mState == s.mState
    369                 && mRoaming == s.mRoaming
    370                 && mIsManualNetworkSelection == s.mIsManualNetworkSelection
    371                 && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong)
    372                 && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort)
    373                 && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric)
    374                 && equalsHandlesNulls(mRadioTechnology, s.mRadioTechnology)
    375                 && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
    376                 && equalsHandlesNulls(mNetworkId, s.mNetworkId)
    377                 && equalsHandlesNulls(mSystemId, s.mSystemId)
    378                 && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
    379                 && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
    380                         s.mCdmaDefaultRoamingIndicator)
    381                 && mIsEmergencyOnly == s.mIsEmergencyOnly);
    382     }
    383 
    384     @Override
    385     public String toString() {
    386         String radioTechnology = new String("Error in radioTechnology");
    387         switch(this.mRadioTechnology) {
    388         case 0:
    389             radioTechnology = "Unknown";
    390             break;
    391         case 1:
    392             radioTechnology = "GPRS";
    393             break;
    394         case 2:
    395             radioTechnology = "EDGE";
    396             break;
    397         case 3:
    398             radioTechnology = "UMTS";
    399             break;
    400         case 4:
    401             radioTechnology = "IS95A";
    402             break;
    403         case 5:
    404             radioTechnology = "IS95B";
    405             break;
    406         case 6:
    407             radioTechnology = "1xRTT";
    408             break;
    409         case 7:
    410             radioTechnology = "EvDo rev. 0";
    411             break;
    412         case 8:
    413             radioTechnology = "EvDo rev. A";
    414             break;
    415         case 9:
    416             radioTechnology = "HSDPA";
    417             break;
    418         case 10:
    419             radioTechnology = "HSUPA";
    420             break;
    421         case 11:
    422             radioTechnology = "HSPA";
    423             break;
    424         case 12:
    425             radioTechnology = "EvDo rev. B";
    426             break;
    427         default:
    428             Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
    429         break;
    430         }
    431 
    432         return (mState + " " + (mRoaming ? "roaming" : "home")
    433                 + " " + mOperatorAlphaLong
    434                 + " " + mOperatorAlphaShort
    435                 + " " + mOperatorNumeric
    436                 + " " + (mIsManualNetworkSelection ? "(manual)" : "")
    437                 + " " + radioTechnology
    438                 + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
    439                 + " " + mNetworkId
    440                 + " " + mSystemId
    441                 + "RoamInd: " + mCdmaRoamingIndicator
    442                 + "DefRoamInd: " + mCdmaDefaultRoamingIndicator
    443                 + "EmergOnly: " + mIsEmergencyOnly);
    444     }
    445 
    446     public void setStateOutOfService() {
    447         mState = STATE_OUT_OF_SERVICE;
    448         mRoaming = false;
    449         mOperatorAlphaLong = null;
    450         mOperatorAlphaShort = null;
    451         mOperatorNumeric = null;
    452         mIsManualNetworkSelection = false;
    453         mRadioTechnology = 0;
    454         mCssIndicator = false;
    455         mNetworkId = -1;
    456         mSystemId = -1;
    457         mCdmaRoamingIndicator = -1;
    458         mCdmaDefaultRoamingIndicator = -1;
    459         mCdmaEriIconIndex = -1;
    460         mCdmaEriIconMode = -1;
    461         mIsEmergencyOnly = false;
    462     }
    463 
    464     // TODO - can't this be combined with the above method?
    465     public void setStateOff() {
    466         mState = STATE_POWER_OFF;
    467         mRoaming = false;
    468         mOperatorAlphaLong = null;
    469         mOperatorAlphaShort = null;
    470         mOperatorNumeric = null;
    471         mIsManualNetworkSelection = false;
    472         mRadioTechnology = 0;
    473         mCssIndicator = false;
    474         mNetworkId = -1;
    475         mSystemId = -1;
    476         mCdmaRoamingIndicator = -1;
    477         mCdmaDefaultRoamingIndicator = -1;
    478         mCdmaEriIconIndex = -1;
    479         mCdmaEriIconMode = -1;
    480         mIsEmergencyOnly = false;
    481     }
    482 
    483     public void setState(int state) {
    484         mState = state;
    485     }
    486 
    487     public void setRoaming(boolean roaming) {
    488         mRoaming = roaming;
    489     }
    490 
    491 
    492     /**
    493      * @hide
    494      */
    495     public void setEmergencyOnly(boolean emergencyOnly) {
    496         mIsEmergencyOnly = emergencyOnly;
    497     }
    498 
    499     /**
    500      * @hide
    501      */
    502     public void setCdmaRoamingIndicator(int roaming) {
    503         this.mCdmaRoamingIndicator = roaming;
    504     }
    505 
    506     /**
    507      * @hide
    508      */
    509     public void setCdmaDefaultRoamingIndicator (int roaming) {
    510         this.mCdmaDefaultRoamingIndicator = roaming;
    511     }
    512 
    513     /**
    514      * @hide
    515      */
    516     public void setCdmaEriIconIndex(int index) {
    517         this.mCdmaEriIconIndex = index;
    518     }
    519 
    520     /**
    521      * @hide
    522      */
    523     public void setCdmaEriIconMode(int mode) {
    524         this.mCdmaEriIconMode = mode;
    525     }
    526 
    527     public void setOperatorName(String longName, String shortName, String numeric) {
    528         mOperatorAlphaLong = longName;
    529         mOperatorAlphaShort = shortName;
    530         mOperatorNumeric = numeric;
    531     }
    532 
    533     /**
    534      * In CDMA, mOperatorAlphaLong can be set from the ERI text.
    535      * This is done from the CDMAPhone and not from the CdmaServiceStateTracker.
    536      *
    537      * @hide
    538      */
    539     public void setCdmaEriText(String longName) {
    540         mOperatorAlphaLong = longName;
    541     }
    542 
    543     public void setIsManualSelection(boolean isManual) {
    544         mIsManualNetworkSelection = isManual;
    545     }
    546 
    547     /**
    548      * Test whether two objects hold the same data values or both are null.
    549      *
    550      * @param a first obj
    551      * @param b second obj
    552      * @return true if two objects equal or both are null
    553      */
    554     private static boolean equalsHandlesNulls (Object a, Object b) {
    555         return (a == null) ? (b == null) : a.equals (b);
    556     }
    557 
    558     /**
    559      * Set ServiceState based on intent notifier map.
    560      *
    561      * @param m intent notifier map
    562      * @hide
    563      */
    564     private void setFromNotifierBundle(Bundle m) {
    565         mState = m.getInt("state");
    566         mRoaming = m.getBoolean("roaming");
    567         mOperatorAlphaLong = m.getString("operator-alpha-long");
    568         mOperatorAlphaShort = m.getString("operator-alpha-short");
    569         mOperatorNumeric = m.getString("operator-numeric");
    570         mIsManualNetworkSelection = m.getBoolean("manual");
    571         mRadioTechnology = m.getInt("radioTechnology");
    572         mCssIndicator = m.getBoolean("cssIndicator");
    573         mNetworkId = m.getInt("networkId");
    574         mSystemId = m.getInt("systemId");
    575         mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
    576         mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
    577         mIsEmergencyOnly = m.getBoolean("emergencyOnly");
    578     }
    579 
    580     /**
    581      * Set intent notifier Bundle based on service state.
    582      *
    583      * @param m intent notifier Bundle
    584      * @hide
    585      */
    586     public void fillInNotifierBundle(Bundle m) {
    587         m.putInt("state", mState);
    588         m.putBoolean("roaming", Boolean.valueOf(mRoaming));
    589         m.putString("operator-alpha-long", mOperatorAlphaLong);
    590         m.putString("operator-alpha-short", mOperatorAlphaShort);
    591         m.putString("operator-numeric", mOperatorNumeric);
    592         m.putBoolean("manual", Boolean.valueOf(mIsManualNetworkSelection));
    593         m.putInt("radioTechnology", mRadioTechnology);
    594         m.putBoolean("cssIndicator", mCssIndicator);
    595         m.putInt("networkId", mNetworkId);
    596         m.putInt("systemId", mSystemId);
    597         m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
    598         m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
    599         m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly));
    600     }
    601 
    602     //***** CDMA
    603     /** @hide */
    604     public void setRadioTechnology(int state) {
    605         this.mRadioTechnology = state;
    606     }
    607 
    608     /** @hide */
    609     public void setCssIndicator(int css) {
    610         this.mCssIndicator = (css != 0);
    611     }
    612 
    613     /** @hide */
    614     public void setSystemAndNetworkId(int systemId, int networkId) {
    615         this.mSystemId = systemId;
    616         this.mNetworkId = networkId;
    617     }
    618 
    619     /** @hide */
    620     public int getRadioTechnology() {
    621         return this.mRadioTechnology;
    622     }
    623 
    624     /** @hide */
    625     public int getCssIndicator() {
    626         return this.mCssIndicator ? 1 : 0;
    627     }
    628 
    629     /** @hide */
    630     public int getNetworkId() {
    631         return this.mNetworkId;
    632     }
    633 
    634     /** @hide */
    635     public int getSystemId() {
    636         return this.mSystemId;
    637     }
    638 }
    639