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.NetworkScanRequest; 28 import android.telephony.ServiceState; 29 import android.telephony.SignalStrength; 30 import android.telephony.TelephonyManager; 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.dataconnection.DataConnection; 45 import com.android.internal.telephony.uicc.IccFileHandler; 46 import com.android.telephony.Rlog; 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 getPendingMmiCodes()172 public List<? extends MmiCode> getPendingMmiCodes() { 173 return new ArrayList<MmiCode>(0); 174 } 175 176 @Override getDataConnectionState()177 public PhoneConstants.DataState getDataConnectionState() { 178 return PhoneConstants.DataState.DISCONNECTED; 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 super.notifyPreciseCallStateChangedP(); 202 } 203 notifyDisconnect(Connection cn)204 public void notifyDisconnect(Connection cn) { 205 mDisconnectRegistrants.notifyResult(cn); 206 207 } 208 notifyImsReason(ImsReasonInfo imsReasonInfo)209 public void notifyImsReason(ImsReasonInfo imsReasonInfo) { 210 mNotifier.notifyImsDisconnectCause(this, imsReasonInfo); 211 } 212 notifyUnknownConnection()213 void notifyUnknownConnection() { 214 mUnknownConnectionRegistrants.notifyResult(this); 215 } 216 notifySuppServiceFailed(SuppService code)217 public void notifySuppServiceFailed(SuppService code) { 218 mSuppServiceFailedRegistrants.notifyResult(code); 219 } 220 notifyServiceStateChanged(ServiceState ss)221 void notifyServiceStateChanged(ServiceState ss) { 222 super.notifyServiceStateChangedP(ss); 223 } 224 225 @Override notifyCallForwardingIndicator()226 public void notifyCallForwardingIndicator() { 227 mNotifier.notifyCallForwardingChanged(this); 228 } 229 canDial()230 public boolean canDial() { 231 int serviceState = getServiceState().getState(); 232 Rlog.v(LOG_TAG, "canDial(): serviceState = " + serviceState); 233 if (serviceState == ServiceState.STATE_POWER_OFF) return false; 234 235 boolean disableCall = TelephonyProperties.disable_call().orElse(false); 236 Rlog.v(LOG_TAG, "canDial(): disableCall = " + disableCall); 237 if (disableCall) return false; 238 239 Rlog.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState()); 240 Rlog.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState()); 241 Rlog.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState()); 242 return !getRingingCall().isRinging() 243 && (!getForegroundCall().getState().isAlive() 244 || !getBackgroundCall().getState().isAlive()); 245 } 246 247 @Override handleInCallMmiCommands(String dialString)248 public boolean handleInCallMmiCommands(String dialString) { 249 return false; 250 } 251 isInCall()252 boolean isInCall() { 253 Call.State foregroundCallState = getForegroundCall().getState(); 254 Call.State backgroundCallState = getBackgroundCall().getState(); 255 Call.State ringingCallState = getRingingCall().getState(); 256 257 return (foregroundCallState.isAlive() || backgroundCallState.isAlive() 258 || ringingCallState.isAlive()); 259 } 260 261 @Override handlePinMmi(String dialString)262 public boolean handlePinMmi(String dialString) { 263 return false; 264 } 265 266 @Override sendUssdResponse(String ussdMessge)267 public void sendUssdResponse(String ussdMessge) { 268 } 269 270 @Override registerForSuppServiceNotification( Handler h, int what, Object obj)271 public void registerForSuppServiceNotification( 272 Handler h, int what, Object obj) { 273 } 274 275 @Override unregisterForSuppServiceNotification(Handler h)276 public void unregisterForSuppServiceNotification(Handler h) { 277 } 278 279 @Override setRadioPower(boolean power)280 public void setRadioPower(boolean power) { 281 } 282 283 @Override getVoiceMailNumber()284 public String getVoiceMailNumber() { 285 return null; 286 } 287 288 @Override getVoiceMailAlphaTag()289 public String getVoiceMailAlphaTag() { 290 return null; 291 } 292 293 @Override getDeviceId()294 public String getDeviceId() { 295 return null; 296 } 297 298 @Override getDeviceSvn()299 public String getDeviceSvn() { 300 return null; 301 } 302 303 @Override getImei()304 public String getImei() { 305 return null; 306 } 307 308 @Override getEsn()309 public String getEsn() { 310 Rlog.e(LOG_TAG, "[VoltePhone] getEsn() is a CDMA method"); 311 return "0"; 312 } 313 314 @Override getMeid()315 public String getMeid() { 316 Rlog.e(LOG_TAG, "[VoltePhone] getMeid() is a CDMA method"); 317 return "0"; 318 } 319 320 @Override getSubscriberId()321 public String getSubscriberId() { 322 return null; 323 } 324 325 @Override getGroupIdLevel1()326 public String getGroupIdLevel1() { 327 return null; 328 } 329 330 @Override getGroupIdLevel2()331 public String getGroupIdLevel2() { 332 return null; 333 } 334 335 @Override getIccSerialNumber()336 public String getIccSerialNumber() { 337 return null; 338 } 339 340 @Override getLine1AlphaTag()341 public String getLine1AlphaTag() { 342 return null; 343 } 344 345 @Override setLine1Number(String alphaTag, String number, Message onComplete)346 public boolean setLine1Number(String alphaTag, String number, Message onComplete) { 347 // FIXME: what to reply for Volte? 348 return false; 349 } 350 351 @Override setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)352 public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, 353 Message onComplete) { 354 // FIXME: what to reply for Volte? 355 AsyncResult.forMessage(onComplete, null, null); 356 onComplete.sendToTarget(); 357 } 358 359 @Override getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)360 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 361 } 362 363 @Override getCallForwardingOption(int commandInterfaceCFReason, int serviceClass, Message onComplete)364 public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass, 365 Message onComplete) { 366 } 367 368 @Override setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)369 public void setCallForwardingOption(int commandInterfaceCFAction, 370 int commandInterfaceCFReason, String dialingNumber, 371 int timerSeconds, Message onComplete) { 372 } 373 374 @Override setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int serviceClass, int timerSeconds, Message onComplete)375 public void setCallForwardingOption(int commandInterfaceCFAction, 376 int commandInterfaceCFReason, String dialingNumber, int serviceClass, 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()476 public boolean isDataAllowed() { 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 getCallBarring(String facility, String password, Message onComplete, int serviceClass)513 public void getCallBarring(String facility, String password, Message onComplete, 514 int serviceClass) { 515 } 516 517 @Override setCallBarring(String facility, boolean lockState, String password, Message onComplete, int serviceClass)518 public void setCallBarring(String facility, boolean lockState, String password, 519 Message onComplete, int serviceClass) { 520 } 521 522 @Override onUpdateIccAvailability()523 protected void onUpdateIccAvailability() { 524 } 525 updatePhoneState()526 void updatePhoneState() { 527 PhoneConstants.State oldState = mState; 528 529 if (getRingingCall().isRinging()) { 530 mState = PhoneConstants.State.RINGING; 531 } else if (getForegroundCall().isIdle() 532 && getBackgroundCall().isIdle()) { 533 mState = PhoneConstants.State.IDLE; 534 } else { 535 mState = PhoneConstants.State.OFFHOOK; 536 } 537 538 if (mState != oldState) { 539 Rlog.d(LOG_TAG, " ^^^ new phone state: " + mState); 540 notifyPhoneStateChanged(); 541 } 542 } 543 } 544