1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.imsphone; 18 19 import android.content.Context; 20 import android.net.LinkProperties; 21 import android.os.AsyncResult; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.os.Registrant; 25 import android.os.RegistrantList; 26 import android.os.SystemProperties; 27 import android.telephony.CellInfo; 28 import android.telephony.CellLocation; 29 import android.telephony.ServiceState; 30 import android.telephony.SignalStrength; 31 import android.telephony.Rlog; 32 33 import com.android.internal.telephony.Call; 34 import com.android.internal.telephony.CallStateException; 35 import com.android.internal.telephony.Connection; 36 import com.android.internal.telephony.dataconnection.DataConnection; 37 import com.android.internal.telephony.cdma.CDMAPhone; 38 import com.android.internal.telephony.gsm.GSMPhone; 39 import com.android.internal.telephony.CallManager; 40 import com.android.internal.telephony.IccCard; 41 import com.android.internal.telephony.IccPhoneBookInterfaceManager; 42 import com.android.internal.telephony.MmiCode; 43 import com.android.internal.telephony.OperatorInfo; 44 import com.android.internal.telephony.Phone; 45 import com.android.internal.telephony.PhoneBase; 46 import com.android.internal.telephony.PhoneConstants; 47 import com.android.internal.telephony.PhoneNotifier; 48 import com.android.internal.telephony.PhoneSubInfo; 49 import com.android.internal.telephony.TelephonyProperties; 50 import com.android.internal.telephony.UUSInfo; 51 import com.android.internal.telephony.uicc.IccFileHandler; 52 53 import java.util.ArrayList; 54 import java.util.List; 55 56 abstract class ImsPhoneBase extends PhoneBase { 57 private static final String LOG_TAG = "ImsPhoneBase"; 58 59 private RegistrantList mRingbackRegistrants = new RegistrantList(); 60 private RegistrantList mOnHoldRegistrants = new RegistrantList(); 61 private PhoneConstants.State mState = PhoneConstants.State.IDLE; 62 63 public ImsPhoneBase(String name, Context context, PhoneNotifier notifier) { 64 super(name, notifier, context, new ImsPhoneCommandInterface(context), false); 65 } 66 67 @Override 68 public Connection dial(String dialString, UUSInfo uusInfo, int videoState) 69 throws CallStateException { 70 // ignore UUSInfo 71 return dial(dialString, videoState); 72 } 73 74 @Override 75 public void migrateFrom(PhoneBase from) { 76 super.migrateFrom(from); 77 migrate(mRingbackRegistrants, ((ImsPhoneBase)from).mRingbackRegistrants); 78 } 79 80 @Override 81 public void registerForRingbackTone(Handler h, int what, Object obj) { 82 mRingbackRegistrants.addUnique(h, what, obj); 83 } 84 85 @Override 86 public void unregisterForRingbackTone(Handler h) { 87 mRingbackRegistrants.remove(h); 88 } 89 90 protected void startRingbackTone() { 91 AsyncResult result = new AsyncResult(null, Boolean.TRUE, null); 92 mRingbackRegistrants.notifyRegistrants(result); 93 } 94 95 protected void stopRingbackTone() { 96 AsyncResult result = new AsyncResult(null, Boolean.FALSE, null); 97 mRingbackRegistrants.notifyRegistrants(result); 98 } 99 100 @Override 101 public void registerForOnHoldTone(Handler h, int what, Object obj) { 102 mOnHoldRegistrants.addUnique(h, what, obj); 103 } 104 105 @Override 106 public void unregisterForOnHoldTone(Handler h) { 107 mOnHoldRegistrants.remove(h); 108 } 109 110 protected void startOnHoldTone() { 111 AsyncResult result = new AsyncResult(null, Boolean.TRUE, null); 112 mOnHoldRegistrants.notifyRegistrants(result); 113 } 114 115 protected void stopOnHoldTone() { 116 AsyncResult result = new AsyncResult(null, Boolean.FALSE, null); 117 mOnHoldRegistrants.notifyRegistrants(result); 118 } 119 120 @Override 121 public ServiceState getServiceState() { 122 // FIXME: we may need to provide this when data connectivity is lost 123 // or when server is down 124 ServiceState s = new ServiceState(); 125 s.setState(ServiceState.STATE_IN_SERVICE); 126 return s; 127 } 128 129 /** 130 * @return all available cell information or null if none. 131 */ 132 @Override 133 public List<CellInfo> getAllCellInfo() { 134 return getServiceStateTracker().getAllCellInfo(); 135 } 136 137 @Override 138 public CellLocation getCellLocation() { 139 return null; 140 } 141 142 @Override 143 public PhoneConstants.State getState() { 144 return mState; 145 } 146 147 @Override 148 public int getPhoneType() { 149 return PhoneConstants.PHONE_TYPE_IMS; 150 } 151 152 @Override 153 public SignalStrength getSignalStrength() { 154 return new SignalStrength(); 155 } 156 157 @Override 158 public boolean getMessageWaitingIndicator() { 159 return false; 160 } 161 162 @Override 163 public boolean getCallForwardingIndicator() { 164 return false; 165 } 166 167 @Override 168 public List<? extends MmiCode> getPendingMmiCodes() { 169 return new ArrayList<MmiCode>(0); 170 } 171 172 @Override 173 public PhoneConstants.DataState getDataConnectionState() { 174 return PhoneConstants.DataState.DISCONNECTED; 175 } 176 177 @Override 178 public PhoneConstants.DataState getDataConnectionState(String apnType) { 179 return PhoneConstants.DataState.DISCONNECTED; 180 } 181 182 @Override 183 public DataActivityState getDataActivityState() { 184 return DataActivityState.NONE; 185 } 186 187 /** 188 * Notify any interested party of a Phone state change 189 * {@link com.android.internal.telephony.PhoneConstants.State} 190 */ 191 /* package */ void notifyPhoneStateChanged() { 192 mNotifier.notifyPhoneState(this); 193 } 194 195 /** 196 * Notify registrants of a change in the call state. This notifies changes in 197 * {@link com.android.internal.telephony.Call.State}. Use this when changes 198 * in the precise call state are needed, else use notifyPhoneStateChanged. 199 */ 200 /* package */ void notifyPreciseCallStateChanged() { 201 /* we'd love it if this was package-scoped*/ 202 super.notifyPreciseCallStateChangedP(); 203 } 204 205 void notifyDisconnect(Connection cn) { 206 mDisconnectRegistrants.notifyResult(cn); 207 } 208 209 void notifyUnknownConnection() { 210 mUnknownConnectionRegistrants.notifyResult(this); 211 } 212 213 void notifySuppServiceFailed(SuppService code) { 214 mSuppServiceFailedRegistrants.notifyResult(code); 215 } 216 217 void notifyServiceStateChanged(ServiceState ss) { 218 super.notifyServiceStateChangedP(ss); 219 } 220 221 @Override 222 public void notifyCallForwardingIndicator() { 223 mNotifier.notifyCallForwardingChanged(this); 224 } 225 226 public boolean canDial() { 227 int serviceState = getServiceState().getState(); 228 Rlog.v(LOG_TAG, "canDial(): serviceState = " + serviceState); 229 if (serviceState == ServiceState.STATE_POWER_OFF) return false; 230 231 String disableCall = SystemProperties.get( 232 TelephonyProperties.PROPERTY_DISABLE_CALL, "false"); 233 Rlog.v(LOG_TAG, "canDial(): disableCall = " + disableCall); 234 if (disableCall.equals("true")) return false; 235 236 Rlog.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState()); 237 Rlog.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState()); 238 Rlog.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState()); 239 return !getRingingCall().isRinging() 240 && (!getForegroundCall().getState().isAlive() 241 || !getBackgroundCall().getState().isAlive()); 242 } 243 244 @Override 245 public boolean handleInCallMmiCommands(String dialString) { 246 return false; 247 } 248 249 boolean isInCall() { 250 Call.State foregroundCallState = getForegroundCall().getState(); 251 Call.State backgroundCallState = getBackgroundCall().getState(); 252 Call.State ringingCallState = getRingingCall().getState(); 253 254 return (foregroundCallState.isAlive() || backgroundCallState.isAlive() 255 || ringingCallState.isAlive()); 256 } 257 258 @Override 259 public boolean handlePinMmi(String dialString) { 260 return false; 261 } 262 263 @Override 264 public void sendUssdResponse(String ussdMessge) { 265 } 266 267 @Override 268 public void registerForSuppServiceNotification( 269 Handler h, int what, Object obj) { 270 } 271 272 @Override 273 public void unregisterForSuppServiceNotification(Handler h) { 274 } 275 276 @Override 277 public void setRadioPower(boolean power) { 278 } 279 280 @Override 281 public String getVoiceMailNumber() { 282 return null; 283 } 284 285 @Override 286 public String getVoiceMailAlphaTag() { 287 return null; 288 } 289 290 @Override 291 public String getDeviceId() { 292 return null; 293 } 294 295 @Override 296 public String getDeviceSvn() { 297 return null; 298 } 299 300 @Override 301 public String getImei() { 302 return null; 303 } 304 305 @Override 306 public String getEsn() { 307 Rlog.e(LOG_TAG, "[VoltePhone] getEsn() is a CDMA method"); 308 return "0"; 309 } 310 311 @Override 312 public String getMeid() { 313 Rlog.e(LOG_TAG, "[VoltePhone] getMeid() is a CDMA method"); 314 return "0"; 315 } 316 317 @Override 318 public String getSubscriberId() { 319 return null; 320 } 321 322 @Override 323 public String getGroupIdLevel1() { 324 return null; 325 } 326 327 @Override 328 public String getIccSerialNumber() { 329 return null; 330 } 331 332 @Override 333 public String getLine1Number() { 334 return null; 335 } 336 337 @Override 338 public String getLine1AlphaTag() { 339 return null; 340 } 341 342 @Override 343 public void setLine1Number(String alphaTag, String number, Message onComplete) { 344 // FIXME: what to reply for Volte? 345 AsyncResult.forMessage(onComplete, null, null); 346 onComplete.sendToTarget(); 347 } 348 349 @Override 350 public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, 351 Message onComplete) { 352 // FIXME: what to reply for Volte? 353 AsyncResult.forMessage(onComplete, null, null); 354 onComplete.sendToTarget(); 355 } 356 357 @Override 358 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 359 } 360 361 @Override 362 public void setCallForwardingOption(int commandInterfaceCFAction, 363 int commandInterfaceCFReason, String dialingNumber, 364 int timerSeconds, Message onComplete) { 365 } 366 367 @Override 368 public void getOutgoingCallerIdDisplay(Message onComplete) { 369 // FIXME: what to reply? 370 AsyncResult.forMessage(onComplete, null, null); 371 onComplete.sendToTarget(); 372 } 373 374 @Override 375 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, 376 Message onComplete) { 377 // FIXME: what's this for Volte? 378 AsyncResult.forMessage(onComplete, null, null); 379 onComplete.sendToTarget(); 380 } 381 382 @Override 383 public void getCallWaiting(Message onComplete) { 384 AsyncResult.forMessage(onComplete, null, null); 385 onComplete.sendToTarget(); 386 } 387 388 @Override 389 public void setCallWaiting(boolean enable, Message onComplete) { 390 Rlog.e(LOG_TAG, "call waiting not supported"); 391 } 392 393 @Override 394 public boolean getIccRecordsLoaded() { 395 return false; 396 } 397 398 @Override 399 public IccCard getIccCard() { 400 return null; 401 } 402 403 @Override 404 public void getAvailableNetworks(Message response) { 405 } 406 407 @Override 408 public void setNetworkSelectionModeAutomatic(Message response) { 409 } 410 411 @Override 412 public void selectNetworkManually( 413 OperatorInfo network, 414 Message response) { 415 } 416 417 @Override 418 public void getNeighboringCids(Message response) { 419 } 420 421 @Override 422 public void getDataCallList(Message response) { 423 } 424 425 public List<DataConnection> getCurrentDataConnectionList () { 426 return null; 427 } 428 429 @Override 430 public void updateServiceLocation() { 431 } 432 433 @Override 434 public void enableLocationUpdates() { 435 } 436 437 @Override 438 public void disableLocationUpdates() { 439 } 440 441 @Override 442 public boolean getDataRoamingEnabled() { 443 return false; 444 } 445 446 @Override 447 public void setDataRoamingEnabled(boolean enable) { 448 } 449 450 @Override 451 public boolean getDataEnabled() { 452 return false; 453 } 454 455 @Override 456 public void setDataEnabled(boolean enable) { 457 } 458 459 460 public boolean enableDataConnectivity() { 461 return false; 462 } 463 464 public boolean disableDataConnectivity() { 465 return false; 466 } 467 468 @Override 469 public boolean isDataConnectivityPossible() { 470 return false; 471 } 472 473 boolean updateCurrentCarrierInProvider() { 474 return false; 475 } 476 477 public void saveClirSetting(int commandInterfaceCLIRMode) { 478 } 479 480 @Override 481 public PhoneSubInfo getPhoneSubInfo(){ 482 return null; 483 } 484 485 @Override 486 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ 487 return null; 488 } 489 490 @Override 491 public IccFileHandler getIccFileHandler(){ 492 return null; 493 } 494 495 @Override 496 public void activateCellBroadcastSms(int activate, Message response) { 497 Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte."); 498 } 499 500 @Override 501 public void getCellBroadcastSmsConfig(Message response) { 502 Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte."); 503 } 504 505 @Override 506 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){ 507 Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte."); 508 } 509 510 //@Override 511 @Override 512 public boolean needsOtaServiceProvisioning() { 513 // FIXME: what's this for Volte? 514 return false; 515 } 516 517 //@Override 518 @Override 519 public LinkProperties getLinkProperties(String apnType) { 520 // FIXME: what's this for Volte? 521 return null; 522 } 523 524 @Override 525 protected void onUpdateIccAvailability() { 526 } 527 528 void updatePhoneState() { 529 PhoneConstants.State oldState = mState; 530 531 if (getRingingCall().isRinging()) { 532 mState = PhoneConstants.State.RINGING; 533 } else if (getForegroundCall().isIdle() 534 && getBackgroundCall().isIdle()) { 535 mState = PhoneConstants.State.IDLE; 536 } else { 537 mState = PhoneConstants.State.OFFHOOK; 538 } 539 540 if (mState != oldState) { 541 Rlog.d(LOG_TAG, " ^^^ new phone state: " + mState); 542 notifyPhoneStateChanged(); 543 } 544 } 545 } 546