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