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