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