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