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