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.os.WorkSource; 27 import android.telephony.CellInfo; 28 import android.telephony.CellLocation; 29 import android.telephony.NetworkScanRequest; 30 import android.telephony.Rlog; 31 import android.telephony.ServiceState; 32 import android.telephony.SignalStrength; 33 import android.util.Pair; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.internal.telephony.Call; 37 import com.android.internal.telephony.Connection; 38 import com.android.internal.telephony.IccCard; 39 import com.android.internal.telephony.IccPhoneBookInterfaceManager; 40 import com.android.internal.telephony.MmiCode; 41 import com.android.internal.telephony.OperatorInfo; 42 import com.android.internal.telephony.Phone; 43 import com.android.internal.telephony.PhoneConstants; 44 import com.android.internal.telephony.PhoneNotifier; 45 import com.android.internal.telephony.TelephonyProperties; 46 import com.android.internal.telephony.dataconnection.DataConnection; 47 import com.android.internal.telephony.uicc.IccFileHandler; 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 139 @Override getServiceState()140 public ServiceState getServiceState() { 141 // FIXME: we may need to provide this when data connectivity is lost 142 // or when server is down 143 ServiceState s = new ServiceState(); 144 s.setVoiceRegState(ServiceState.STATE_IN_SERVICE); 145 return s; 146 } 147 148 /** 149 * @return all available cell information or null if none. 150 */ 151 @Override getAllCellInfo(WorkSource workSource)152 public List<CellInfo> getAllCellInfo(WorkSource workSource) { 153 return getServiceStateTracker().getAllCellInfo(workSource); 154 } 155 156 @Override getCellLocation(WorkSource workSource)157 public CellLocation getCellLocation(WorkSource workSource) { 158 return null; 159 } 160 161 @Override getState()162 public PhoneConstants.State getState() { 163 return mState; 164 } 165 166 @Override getPhoneType()167 public int getPhoneType() { 168 return PhoneConstants.PHONE_TYPE_IMS; 169 } 170 171 @Override getSignalStrength()172 public SignalStrength getSignalStrength() { 173 return new SignalStrength(); 174 } 175 176 @Override getMessageWaitingIndicator()177 public boolean getMessageWaitingIndicator() { 178 return false; 179 } 180 181 @Override getCallForwardingIndicator()182 public boolean getCallForwardingIndicator() { 183 return false; 184 } 185 186 @Override getPendingMmiCodes()187 public List<? extends MmiCode> getPendingMmiCodes() { 188 return new ArrayList<MmiCode>(0); 189 } 190 191 @Override getDataConnectionState()192 public PhoneConstants.DataState getDataConnectionState() { 193 return PhoneConstants.DataState.DISCONNECTED; 194 } 195 196 @Override getDataConnectionState(String apnType)197 public PhoneConstants.DataState getDataConnectionState(String apnType) { 198 return PhoneConstants.DataState.DISCONNECTED; 199 } 200 201 @Override getDataActivityState()202 public DataActivityState getDataActivityState() { 203 return DataActivityState.NONE; 204 } 205 206 /** 207 * Notify any interested party of a Phone state change 208 * {@link com.android.internal.telephony.PhoneConstants.State} 209 */ notifyPhoneStateChanged()210 public void notifyPhoneStateChanged() { 211 mNotifier.notifyPhoneState(this); 212 } 213 214 /** 215 * Notify registrants of a change in the call state. This notifies changes in 216 * {@link com.android.internal.telephony.Call.State}. Use this when changes 217 * in the precise call state are needed, else use notifyPhoneStateChanged. 218 */ notifyPreciseCallStateChanged()219 public void notifyPreciseCallStateChanged() { 220 /* we'd love it if this was package-scoped*/ 221 super.notifyPreciseCallStateChangedP(); 222 } 223 notifyDisconnect(Connection cn)224 public void notifyDisconnect(Connection cn) { 225 mDisconnectRegistrants.notifyResult(cn); 226 227 mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause()); 228 } 229 notifyUnknownConnection()230 void notifyUnknownConnection() { 231 mUnknownConnectionRegistrants.notifyResult(this); 232 } 233 notifySuppServiceFailed(SuppService code)234 public void notifySuppServiceFailed(SuppService code) { 235 mSuppServiceFailedRegistrants.notifyResult(code); 236 } 237 notifyServiceStateChanged(ServiceState ss)238 void notifyServiceStateChanged(ServiceState ss) { 239 super.notifyServiceStateChangedP(ss); 240 } 241 242 @Override notifyCallForwardingIndicator()243 public void notifyCallForwardingIndicator() { 244 mNotifier.notifyCallForwardingChanged(this); 245 } 246 canDial()247 public boolean canDial() { 248 int serviceState = getServiceState().getState(); 249 Rlog.v(LOG_TAG, "canDial(): serviceState = " + serviceState); 250 if (serviceState == ServiceState.STATE_POWER_OFF) return false; 251 252 String disableCall = SystemProperties.get( 253 TelephonyProperties.PROPERTY_DISABLE_CALL, "false"); 254 Rlog.v(LOG_TAG, "canDial(): disableCall = " + disableCall); 255 if (disableCall.equals("true")) return false; 256 257 Rlog.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState()); 258 Rlog.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState()); 259 Rlog.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState()); 260 return !getRingingCall().isRinging() 261 && (!getForegroundCall().getState().isAlive() 262 || !getBackgroundCall().getState().isAlive()); 263 } 264 265 @Override handleInCallMmiCommands(String dialString)266 public boolean handleInCallMmiCommands(String dialString) { 267 return false; 268 } 269 isInCall()270 boolean isInCall() { 271 Call.State foregroundCallState = getForegroundCall().getState(); 272 Call.State backgroundCallState = getBackgroundCall().getState(); 273 Call.State ringingCallState = getRingingCall().getState(); 274 275 return (foregroundCallState.isAlive() || backgroundCallState.isAlive() 276 || ringingCallState.isAlive()); 277 } 278 279 @Override handlePinMmi(String dialString)280 public boolean handlePinMmi(String dialString) { 281 return false; 282 } 283 284 @Override sendUssdResponse(String ussdMessge)285 public void sendUssdResponse(String ussdMessge) { 286 } 287 288 @Override registerForSuppServiceNotification( Handler h, int what, Object obj)289 public void registerForSuppServiceNotification( 290 Handler h, int what, Object obj) { 291 } 292 293 @Override unregisterForSuppServiceNotification(Handler h)294 public void unregisterForSuppServiceNotification(Handler h) { 295 } 296 297 @Override setRadioPower(boolean power)298 public void setRadioPower(boolean power) { 299 } 300 301 @Override getVoiceMailNumber()302 public String getVoiceMailNumber() { 303 return null; 304 } 305 306 @Override getVoiceMailAlphaTag()307 public String getVoiceMailAlphaTag() { 308 return null; 309 } 310 311 @Override getDeviceId()312 public String getDeviceId() { 313 return null; 314 } 315 316 @Override getDeviceSvn()317 public String getDeviceSvn() { 318 return null; 319 } 320 321 @Override getImei()322 public String getImei() { 323 return null; 324 } 325 326 @Override getEsn()327 public String getEsn() { 328 Rlog.e(LOG_TAG, "[VoltePhone] getEsn() is a CDMA method"); 329 return "0"; 330 } 331 332 @Override getMeid()333 public String getMeid() { 334 Rlog.e(LOG_TAG, "[VoltePhone] getMeid() is a CDMA method"); 335 return "0"; 336 } 337 338 @Override getSubscriberId()339 public String getSubscriberId() { 340 return null; 341 } 342 343 @Override getGroupIdLevel1()344 public String getGroupIdLevel1() { 345 return null; 346 } 347 348 @Override getGroupIdLevel2()349 public String getGroupIdLevel2() { 350 return null; 351 } 352 353 @Override getIccSerialNumber()354 public String getIccSerialNumber() { 355 return null; 356 } 357 358 @Override getLine1Number()359 public String getLine1Number() { 360 return null; 361 } 362 363 @Override getLine1AlphaTag()364 public String getLine1AlphaTag() { 365 return null; 366 } 367 368 @Override setLine1Number(String alphaTag, String number, Message onComplete)369 public boolean setLine1Number(String alphaTag, String number, Message onComplete) { 370 // FIXME: what to reply for Volte? 371 return false; 372 } 373 374 @Override setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)375 public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, 376 Message onComplete) { 377 // FIXME: what to reply for Volte? 378 AsyncResult.forMessage(onComplete, null, null); 379 onComplete.sendToTarget(); 380 } 381 382 @Override getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)383 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 384 } 385 386 @Override setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)387 public void setCallForwardingOption(int commandInterfaceCFAction, 388 int commandInterfaceCFReason, String dialingNumber, 389 int timerSeconds, Message onComplete) { 390 } 391 392 @Override getOutgoingCallerIdDisplay(Message onComplete)393 public void getOutgoingCallerIdDisplay(Message onComplete) { 394 // FIXME: what to reply? 395 AsyncResult.forMessage(onComplete, null, null); 396 onComplete.sendToTarget(); 397 } 398 399 @Override setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)400 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, 401 Message onComplete) { 402 // FIXME: what's this for Volte? 403 AsyncResult.forMessage(onComplete, null, null); 404 onComplete.sendToTarget(); 405 } 406 407 @Override getCallWaiting(Message onComplete)408 public void getCallWaiting(Message onComplete) { 409 AsyncResult.forMessage(onComplete, null, null); 410 onComplete.sendToTarget(); 411 } 412 413 @Override setCallWaiting(boolean enable, Message onComplete)414 public void setCallWaiting(boolean enable, Message onComplete) { 415 Rlog.e(LOG_TAG, "call waiting not supported"); 416 } 417 418 @Override getIccRecordsLoaded()419 public boolean getIccRecordsLoaded() { 420 return false; 421 } 422 423 @Override getIccCard()424 public IccCard getIccCard() { 425 return null; 426 } 427 428 @Override getAvailableNetworks(Message response)429 public void getAvailableNetworks(Message response) { 430 } 431 432 @Override startNetworkScan(NetworkScanRequest nsr, Message response)433 public void startNetworkScan(NetworkScanRequest nsr, Message response) { 434 } 435 436 @Override stopNetworkScan(Message response)437 public void stopNetworkScan(Message response) { 438 } 439 440 @Override setNetworkSelectionModeAutomatic(Message response)441 public void setNetworkSelectionModeAutomatic(Message response) { 442 } 443 444 @Override selectNetworkManually(OperatorInfo network, boolean persistSelection, Message response)445 public void selectNetworkManually(OperatorInfo network, boolean persistSelection, 446 Message response) { 447 } 448 getCurrentDataConnectionList()449 public List<DataConnection> getCurrentDataConnectionList () { 450 return null; 451 } 452 453 @Override updateServiceLocation()454 public void updateServiceLocation() { 455 } 456 457 @Override enableLocationUpdates()458 public void enableLocationUpdates() { 459 } 460 461 @Override disableLocationUpdates()462 public void disableLocationUpdates() { 463 } 464 465 @Override getDataRoamingEnabled()466 public boolean getDataRoamingEnabled() { 467 return false; 468 } 469 470 @Override setDataRoamingEnabled(boolean enable)471 public void setDataRoamingEnabled(boolean enable) { 472 } 473 474 @Override isUserDataEnabled()475 public boolean isUserDataEnabled() { 476 return false; 477 } 478 479 @Override isDataEnabled()480 public boolean isDataEnabled() { 481 return false; 482 } 483 484 @Override setUserDataEnabled(boolean enable)485 public void setUserDataEnabled(boolean enable) { 486 } 487 488 enableDataConnectivity()489 public boolean enableDataConnectivity() { 490 return false; 491 } 492 disableDataConnectivity()493 public boolean disableDataConnectivity() { 494 return false; 495 } 496 497 @Override isDataAllowed()498 public boolean isDataAllowed() { 499 return false; 500 } 501 502 @Override getIccPhoneBookInterfaceManager()503 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ 504 return null; 505 } 506 507 @Override getIccFileHandler()508 public IccFileHandler getIccFileHandler(){ 509 return null; 510 } 511 512 @Override activateCellBroadcastSms(int activate, Message response)513 public void activateCellBroadcastSms(int activate, Message response) { 514 Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte."); 515 } 516 517 @Override getCellBroadcastSmsConfig(Message response)518 public void getCellBroadcastSmsConfig(Message response) { 519 Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte."); 520 } 521 522 @Override setCellBroadcastSmsConfig(int[] configValuesArray, Message response)523 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){ 524 Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte."); 525 } 526 527 //@Override 528 @Override needsOtaServiceProvisioning()529 public boolean needsOtaServiceProvisioning() { 530 // FIXME: what's this for Volte? 531 return false; 532 } 533 534 //@Override 535 @Override getLinkProperties(String apnType)536 public LinkProperties getLinkProperties(String apnType) { 537 // FIXME: what's this for Volte? 538 return null; 539 } 540 541 @Override getCallBarring(String facility, String password, Message onComplete, int serviceClass)542 public void getCallBarring(String facility, String password, Message onComplete, 543 int serviceClass) { 544 } 545 546 @Override setCallBarring(String facility, boolean lockState, String password, Message onComplete, int serviceClass)547 public void setCallBarring(String facility, boolean lockState, String password, 548 Message onComplete, int serviceClass) { 549 } 550 551 @Override onUpdateIccAvailability()552 protected void onUpdateIccAvailability() { 553 } 554 updatePhoneState()555 void updatePhoneState() { 556 PhoneConstants.State oldState = mState; 557 558 if (getRingingCall().isRinging()) { 559 mState = PhoneConstants.State.RINGING; 560 } else if (getForegroundCall().isIdle() 561 && getBackgroundCall().isIdle()) { 562 mState = PhoneConstants.State.IDLE; 563 } else { 564 mState = PhoneConstants.State.OFFHOOK; 565 } 566 567 if (mState != oldState) { 568 Rlog.d(LOG_TAG, " ^^^ new phone state: " + mState); 569 notifyPhoneStateChanged(); 570 } 571 } 572 } 573