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