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