ImsPhoneBase.java revision 5d0d72d9b7dc34c93303f6732541bbb74fed53da
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
17package com.android.internal.telephony.imsphone;
18
19import android.content.Context;
20import android.net.LinkProperties;
21import android.os.AsyncResult;
22import android.os.Handler;
23import android.os.Message;
24import android.os.Registrant;
25import android.os.RegistrantList;
26import android.os.SystemProperties;
27import android.telephony.CellInfo;
28import android.telephony.CellLocation;
29import android.telephony.ServiceState;
30import android.telephony.SignalStrength;
31import android.telephony.Rlog;
32
33import com.android.internal.telephony.Call;
34import com.android.internal.telephony.CallStateException;
35import com.android.internal.telephony.Connection;
36import com.android.internal.telephony.dataconnection.DataConnection;
37import com.android.internal.telephony.cdma.CDMAPhone;
38import com.android.internal.telephony.gsm.GSMPhone;
39import com.android.internal.telephony.CallManager;
40import com.android.internal.telephony.IccCard;
41import com.android.internal.telephony.IccPhoneBookInterfaceManager;
42import com.android.internal.telephony.MmiCode;
43import com.android.internal.telephony.OperatorInfo;
44import com.android.internal.telephony.Phone;
45import com.android.internal.telephony.PhoneBase;
46import com.android.internal.telephony.PhoneConstants;
47import com.android.internal.telephony.PhoneNotifier;
48import com.android.internal.telephony.PhoneSubInfo;
49import com.android.internal.telephony.TelephonyProperties;
50import com.android.internal.telephony.UUSInfo;
51import com.android.internal.telephony.uicc.IccFileHandler;
52
53import java.util.ArrayList;
54import java.util.List;
55
56abstract class ImsPhoneBase extends PhoneBase {
57    private static final String LOG_TAG = "ImsPhoneBase";
58
59    private RegistrantList mRingbackRegistrants = new RegistrantList();
60    private RegistrantList mOnHoldRegistrants = new RegistrantList();
61    private PhoneConstants.State mState = PhoneConstants.State.IDLE;
62
63    public ImsPhoneBase(String name, Context context, PhoneNotifier notifier) {
64        super(name, notifier, context, new ImsPhoneCommandInterface(context), false);
65    }
66
67    @Override
68    public Connection dial(String dialString, UUSInfo uusInfo, int videoState)
69            throws CallStateException {
70        // ignore UUSInfo
71        return dial(dialString, videoState);
72    }
73
74    void migrateFrom(ImsPhoneBase from) {
75        migrate(mRingbackRegistrants, from.mRingbackRegistrants);
76        migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
77        migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
78        migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
79        migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
80        migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
81        migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
82        migrate(mMmiRegistrants, from.mMmiRegistrants);
83        migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
84        migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
85    }
86
87    static void migrate(RegistrantList to, RegistrantList from) {
88        from.removeCleared();
89        for (int i = 0, n = from.size(); i < n; i++) {
90            to.add((Registrant) from.get(i));
91        }
92    }
93
94    @Override
95    public void registerForRingbackTone(Handler h, int what, Object obj) {
96        mRingbackRegistrants.addUnique(h, what, obj);
97    }
98
99    @Override
100    public void unregisterForRingbackTone(Handler h) {
101        mRingbackRegistrants.remove(h);
102    }
103
104    protected void startRingbackTone() {
105        AsyncResult result = new AsyncResult(null, Boolean.TRUE, null);
106        mRingbackRegistrants.notifyRegistrants(result);
107    }
108
109    protected void stopRingbackTone() {
110        AsyncResult result = new AsyncResult(null, Boolean.FALSE, null);
111        mRingbackRegistrants.notifyRegistrants(result);
112    }
113
114    @Override
115    public void registerForOnHoldTone(Handler h, int what, Object obj) {
116        mOnHoldRegistrants.addUnique(h, what, obj);
117    }
118
119    @Override
120    public void unregisterForOnHoldTone(Handler h) {
121        mOnHoldRegistrants.remove(h);
122    }
123
124    protected void startOnHoldTone() {
125        AsyncResult result = new AsyncResult(null, Boolean.TRUE, null);
126        mOnHoldRegistrants.notifyRegistrants(result);
127    }
128
129    protected void stopOnHoldTone() {
130        AsyncResult result = new AsyncResult(null, Boolean.FALSE, null);
131        mOnHoldRegistrants.notifyRegistrants(result);
132    }
133
134    @Override
135    public ServiceState getServiceState() {
136        // FIXME: we may need to provide this when data connectivity is lost
137        // or when server is down
138        ServiceState s = new ServiceState();
139        s.setState(ServiceState.STATE_IN_SERVICE);
140        return s;
141    }
142
143    /**
144     * @return all available cell information or null if none.
145     */
146    @Override
147    public List<CellInfo> getAllCellInfo() {
148        return getServiceStateTracker().getAllCellInfo();
149    }
150
151    @Override
152    public CellLocation getCellLocation() {
153        return null;
154    }
155
156    @Override
157    public PhoneConstants.State getState() {
158        return mState;
159    }
160
161    @Override
162    public int getPhoneType() {
163        return PhoneConstants.PHONE_TYPE_IMS;
164    }
165
166    @Override
167    public SignalStrength getSignalStrength() {
168        return new SignalStrength();
169    }
170
171    @Override
172    public boolean getMessageWaitingIndicator() {
173        return false;
174    }
175
176    @Override
177    public boolean getCallForwardingIndicator() {
178        return false;
179    }
180
181    @Override
182    public List<? extends MmiCode> getPendingMmiCodes() {
183        return new ArrayList<MmiCode>(0);
184    }
185
186    @Override
187    public PhoneConstants.DataState getDataConnectionState() {
188        return PhoneConstants.DataState.DISCONNECTED;
189    }
190
191    @Override
192    public PhoneConstants.DataState getDataConnectionState(String apnType) {
193        return PhoneConstants.DataState.DISCONNECTED;
194    }
195
196    @Override
197    public DataActivityState getDataActivityState() {
198        return DataActivityState.NONE;
199    }
200
201    /**
202     * Notify any interested party of a Phone state change
203     * {@link com.android.internal.telephony.PhoneConstants.State}
204     */
205    /* package */ void notifyPhoneStateChanged() {
206        mNotifier.notifyPhoneState(this);
207    }
208
209    /**
210     * Notify registrants of a change in the call state. This notifies changes in
211     * {@link com.android.internal.telephony.Call.State}. Use this when changes
212     * in the precise call state are needed, else use notifyPhoneStateChanged.
213     */
214    /* package */ void notifyPreciseCallStateChanged() {
215        /* we'd love it if this was package-scoped*/
216        super.notifyPreciseCallStateChangedP();
217    }
218
219    void notifyNewRingingConnection(Connection c) {
220        Phone defaultPhone = CallManager.getInstance().getDefaultPhone();
221        if ( defaultPhone != null && defaultPhone.getPhoneType() ==
222                PhoneConstants.PHONE_TYPE_GSM ) {
223           ((GSMPhone) defaultPhone).notifyNewRingingConnection(c);
224        } else { // Should be CDMA - also go here by default
225            ((CDMAPhone) defaultPhone).notifyNewRingingConnection(c);
226        }
227    }
228
229    void notifyDisconnect(Connection cn) {
230        mDisconnectRegistrants.notifyResult(cn);
231    }
232
233    void notifyUnknownConnection() {
234        mUnknownConnectionRegistrants.notifyResult(this);
235    }
236
237    void notifySuppServiceFailed(SuppService code) {
238        mSuppServiceFailedRegistrants.notifyResult(code);
239    }
240
241    void notifyServiceStateChanged(ServiceState ss) {
242        super.notifyServiceStateChangedP(ss);
243    }
244
245    @Override
246    public void notifyCallForwardingIndicator() {
247        mNotifier.notifyCallForwardingChanged(this);
248    }
249
250    public boolean canDial() {
251        int serviceState = getServiceState().getState();
252        Rlog.v(LOG_TAG, "canDial(): serviceState = " + serviceState);
253        if (serviceState == ServiceState.STATE_POWER_OFF) return false;
254
255        String disableCall = SystemProperties.get(
256                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
257        Rlog.v(LOG_TAG, "canDial(): disableCall = " + disableCall);
258        if (disableCall.equals("true")) return false;
259
260        Rlog.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState());
261        Rlog.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState());
262        Rlog.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState());
263        return !getRingingCall().isRinging()
264                && (!getForegroundCall().getState().isAlive()
265                    || !getBackgroundCall().getState().isAlive());
266    }
267
268    @Override
269    public boolean handleInCallMmiCommands(String dialString) {
270        return false;
271    }
272
273    boolean isInCall() {
274        Call.State foregroundCallState = getForegroundCall().getState();
275        Call.State backgroundCallState = getBackgroundCall().getState();
276        Call.State ringingCallState = getRingingCall().getState();
277
278       return (foregroundCallState.isAlive() || backgroundCallState.isAlive()
279               || ringingCallState.isAlive());
280    }
281
282    @Override
283    public boolean handlePinMmi(String dialString) {
284        return false;
285    }
286
287    @Override
288    public void sendUssdResponse(String ussdMessge) {
289    }
290
291    @Override
292    public void registerForSuppServiceNotification(
293            Handler h, int what, Object obj) {
294    }
295
296    @Override
297    public void unregisterForSuppServiceNotification(Handler h) {
298    }
299
300    @Override
301    public void setRadioPower(boolean power) {
302    }
303
304    @Override
305    public String getVoiceMailNumber() {
306        return null;
307    }
308
309    @Override
310    public String getVoiceMailAlphaTag() {
311        return null;
312    }
313
314    @Override
315    public String getDeviceId() {
316        return null;
317    }
318
319    @Override
320    public String getDeviceSvn() {
321        return null;
322    }
323
324    @Override
325    public String getImei() {
326        return null;
327    }
328
329    @Override
330    public String getEsn() {
331        Rlog.e(LOG_TAG, "[VoltePhone] getEsn() is a CDMA method");
332        return "0";
333    }
334
335    @Override
336    public String getMeid() {
337        Rlog.e(LOG_TAG, "[VoltePhone] getMeid() is a CDMA method");
338        return "0";
339    }
340
341    @Override
342    public String getSubscriberId() {
343        return null;
344    }
345
346    @Override
347    public String getGroupIdLevel1() {
348        return null;
349    }
350
351    @Override
352    public String getIccSerialNumber() {
353        return null;
354    }
355
356    @Override
357    public String getLine1Number() {
358        return null;
359    }
360
361    @Override
362    public String getLine1AlphaTag() {
363        return null;
364    }
365
366    @Override
367    public void setLine1Number(String alphaTag, String number, Message onComplete) {
368        // FIXME: what to reply for Volte?
369        AsyncResult.forMessage(onComplete, null, null);
370        onComplete.sendToTarget();
371    }
372
373    @Override
374    public void setVoiceMailNumber(String alphaTag, String voiceMailNumber,
375            Message onComplete) {
376        // FIXME: what to reply for Volte?
377        AsyncResult.forMessage(onComplete, null, null);
378        onComplete.sendToTarget();
379    }
380
381    @Override
382    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
383    }
384
385    @Override
386    public void setCallForwardingOption(int commandInterfaceCFAction,
387            int commandInterfaceCFReason, String dialingNumber,
388            int timerSeconds, Message onComplete) {
389    }
390
391    @Override
392    public void getOutgoingCallerIdDisplay(Message onComplete) {
393        // FIXME: what to reply?
394        AsyncResult.forMessage(onComplete, null, null);
395        onComplete.sendToTarget();
396    }
397
398    @Override
399    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
400            Message onComplete) {
401        // FIXME: what's this for Volte?
402        AsyncResult.forMessage(onComplete, null, null);
403        onComplete.sendToTarget();
404    }
405
406    @Override
407    public void getCallWaiting(Message onComplete) {
408        AsyncResult.forMessage(onComplete, null, null);
409        onComplete.sendToTarget();
410    }
411
412    @Override
413    public void setCallWaiting(boolean enable, Message onComplete) {
414        Rlog.e(LOG_TAG, "call waiting not supported");
415    }
416
417    @Override
418    public boolean getIccRecordsLoaded() {
419        return false;
420    }
421
422    @Override
423    public IccCard getIccCard() {
424        return null;
425    }
426
427    @Override
428    public void getAvailableNetworks(Message response) {
429    }
430
431    @Override
432    public void setNetworkSelectionModeAutomatic(Message response) {
433    }
434
435    @Override
436    public void selectNetworkManually(
437            OperatorInfo network,
438            Message response) {
439    }
440
441    @Override
442    public void getNeighboringCids(Message response) {
443    }
444
445    @Override
446    public void getDataCallList(Message response) {
447    }
448
449    public List<DataConnection> getCurrentDataConnectionList () {
450        return null;
451    }
452
453    @Override
454    public void updateServiceLocation() {
455    }
456
457    @Override
458    public void enableLocationUpdates() {
459    }
460
461    @Override
462    public void disableLocationUpdates() {
463    }
464
465    @Override
466    public boolean getDataRoamingEnabled() {
467        return false;
468    }
469
470    @Override
471    public void setDataRoamingEnabled(boolean enable) {
472    }
473
474    @Override
475    public boolean getDataEnabled() {
476        return false;
477    }
478
479    @Override
480    public void setDataEnabled(boolean enable) {
481    }
482
483
484    public boolean enableDataConnectivity() {
485        return false;
486    }
487
488    public boolean disableDataConnectivity() {
489        return false;
490    }
491
492    @Override
493    public boolean isDataConnectivityPossible() {
494        return false;
495    }
496
497    boolean updateCurrentCarrierInProvider() {
498        return false;
499    }
500
501    public void saveClirSetting(int commandInterfaceCLIRMode) {
502    }
503
504    @Override
505    public PhoneSubInfo getPhoneSubInfo(){
506        return null;
507    }
508
509    @Override
510    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
511        return null;
512    }
513
514    @Override
515    public IccFileHandler getIccFileHandler(){
516        return null;
517    }
518
519    @Override
520    public void activateCellBroadcastSms(int activate, Message response) {
521        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
522    }
523
524    @Override
525    public void getCellBroadcastSmsConfig(Message response) {
526        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
527    }
528
529    @Override
530    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
531        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
532    }
533
534    //@Override
535    @Override
536    public boolean needsOtaServiceProvisioning() {
537        // FIXME: what's this for Volte?
538        return false;
539    }
540
541    //@Override
542    @Override
543    public LinkProperties getLinkProperties(String apnType) {
544        // FIXME: what's this for Volte?
545        return null;
546    }
547
548    @Override
549    protected void onUpdateIccAvailability() {
550    }
551
552    void updatePhoneState() {
553        PhoneConstants.State oldState = mState;
554
555        if (getRingingCall().isRinging()) {
556            mState = PhoneConstants.State.RINGING;
557        } else if (getForegroundCall().isIdle()
558                && getBackgroundCall().isIdle()) {
559            mState = PhoneConstants.State.IDLE;
560        } else {
561            mState = PhoneConstants.State.OFFHOOK;
562        }
563
564        if (mState != oldState) {
565            Rlog.d(LOG_TAG, " ^^^ new phone state: " + mState);
566            notifyPhoneStateChanged();
567        }
568    }
569}
570