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