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