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