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