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