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