ImsPhoneBase.java revision fe4a960eef43178ab7284e8fd470d83a3b107427
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.RegistrantList;
25import android.os.SystemProperties;
26import android.os.WorkSource;
27import android.telephony.CellInfo;
28import android.telephony.CellLocation;
29import android.telephony.Rlog;
30import android.telephony.ServiceState;
31import android.telephony.SignalStrength;
32import android.util.Pair;
33
34import com.android.internal.telephony.Call;
35import com.android.internal.telephony.Connection;
36import com.android.internal.telephony.IccCard;
37import com.android.internal.telephony.IccPhoneBookInterfaceManager;
38import com.android.internal.telephony.MmiCode;
39import com.android.internal.telephony.OperatorInfo;
40import com.android.internal.telephony.Phone;
41import com.android.internal.telephony.PhoneConstants;
42import com.android.internal.telephony.PhoneNotifier;
43import com.android.internal.telephony.TelephonyProperties;
44import com.android.internal.telephony.dataconnection.DataConnection;
45import com.android.internal.telephony.uicc.IccFileHandler;
46
47import java.util.ArrayList;
48import java.util.List;
49
50abstract 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
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
64    public void migrateFrom(Phone from) {
65        super.migrateFrom(from);
66        migrate(mRingbackRegistrants, ((ImsPhoneBase)from).mRingbackRegistrants);
67    }
68
69    @Override
70    public void registerForRingbackTone(Handler h, int what, Object obj) {
71        mRingbackRegistrants.addUnique(h, what, obj);
72    }
73
74    @Override
75    public void unregisterForRingbackTone(Handler h) {
76        mRingbackRegistrants.remove(h);
77    }
78
79    @Override
80    public void startRingbackTone() {
81        AsyncResult result = new AsyncResult(null, Boolean.TRUE, null);
82        mRingbackRegistrants.notifyRegistrants(result);
83    }
84
85    @Override
86    public void stopRingbackTone() {
87        AsyncResult result = new AsyncResult(null, Boolean.FALSE, null);
88        mRingbackRegistrants.notifyRegistrants(result);
89    }
90
91    @Override
92    public void registerForOnHoldTone(Handler h, int what, Object obj) {
93        mOnHoldRegistrants.addUnique(h, what, obj);
94    }
95
96    @Override
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     */
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     */
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
122    public void registerForTtyModeReceived(Handler h, int what, Object obj){
123        mTtyModeReceivedRegistrants.addUnique(h, what, obj);
124    }
125
126    @Override
127    public void unregisterForTtyModeReceived(Handler h) {
128        mTtyModeReceivedRegistrants.remove(h);
129    }
130
131    public void onTtyModeReceived(int mode) {
132        AsyncResult result = new AsyncResult(null, Integer.valueOf(mode), null);
133        mTtyModeReceivedRegistrants.notifyRegistrants(result);
134    }
135
136    @Override
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
149    public List<CellInfo> getAllCellInfo(WorkSource workSource) {
150        return getServiceStateTracker().getAllCellInfo(workSource);
151    }
152
153    @Override
154    public CellLocation getCellLocation(WorkSource workSource) {
155        return null;
156    }
157
158    @Override
159    public PhoneConstants.State getState() {
160        return mState;
161    }
162
163    @Override
164    public int getPhoneType() {
165        return PhoneConstants.PHONE_TYPE_IMS;
166    }
167
168    @Override
169    public SignalStrength getSignalStrength() {
170        return new SignalStrength();
171    }
172
173    @Override
174    public boolean getMessageWaitingIndicator() {
175        return false;
176    }
177
178    @Override
179    public boolean getCallForwardingIndicator() {
180        return false;
181    }
182
183    @Override
184    public List<? extends MmiCode> getPendingMmiCodes() {
185        return new ArrayList<MmiCode>(0);
186    }
187
188    @Override
189    public PhoneConstants.DataState getDataConnectionState() {
190        return PhoneConstants.DataState.DISCONNECTED;
191    }
192
193    @Override
194    public PhoneConstants.DataState getDataConnectionState(String apnType) {
195        return PhoneConstants.DataState.DISCONNECTED;
196    }
197
198    @Override
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     */
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     */
216    public void notifyPreciseCallStateChanged() {
217        /* we'd love it if this was package-scoped*/
218        super.notifyPreciseCallStateChangedP();
219    }
220
221    public void notifyDisconnect(Connection cn) {
222        mDisconnectRegistrants.notifyResult(cn);
223
224        mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
225    }
226
227    void notifyUnknownConnection() {
228        mUnknownConnectionRegistrants.notifyResult(this);
229    }
230
231    void notifySuppServiceFailed(SuppService code) {
232        mSuppServiceFailedRegistrants.notifyResult(code);
233    }
234
235    void notifyServiceStateChanged(ServiceState ss) {
236        super.notifyServiceStateChangedP(ss);
237    }
238
239    @Override
240    public void notifyCallForwardingIndicator() {
241        mNotifier.notifyCallForwardingChanged(this);
242    }
243
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
263    public boolean handleInCallMmiCommands(String dialString) {
264        return false;
265    }
266
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
277    public boolean handlePinMmi(String dialString) {
278        return false;
279    }
280
281    @Override
282    public void sendUssdResponse(String ussdMessge) {
283    }
284
285    @Override
286    public void registerForSuppServiceNotification(
287            Handler h, int what, Object obj) {
288    }
289
290    @Override
291    public void unregisterForSuppServiceNotification(Handler h) {
292    }
293
294    @Override
295    public void setRadioPower(boolean power) {
296    }
297
298    @Override
299    public String getVoiceMailNumber() {
300        return null;
301    }
302
303    @Override
304    public String getVoiceMailAlphaTag() {
305        return null;
306    }
307
308    @Override
309    public String getDeviceId() {
310        return null;
311    }
312
313    @Override
314    public String getDeviceSvn() {
315        return null;
316    }
317
318    @Override
319    public String getImei() {
320        return null;
321    }
322
323    @Override
324    public String getEsn() {
325        Rlog.e(LOG_TAG, "[VoltePhone] getEsn() is a CDMA method");
326        return "0";
327    }
328
329    @Override
330    public String getMeid() {
331        Rlog.e(LOG_TAG, "[VoltePhone] getMeid() is a CDMA method");
332        return "0";
333    }
334
335    @Override
336    public String getSubscriberId() {
337        return null;
338    }
339
340    @Override
341    public String getGroupIdLevel1() {
342        return null;
343    }
344
345    @Override
346    public String getGroupIdLevel2() {
347        return null;
348    }
349
350    @Override
351    public String getIccSerialNumber() {
352        return null;
353    }
354
355    @Override
356    public String getLine1Number() {
357        return null;
358    }
359
360    @Override
361    public String getLine1AlphaTag() {
362        return null;
363    }
364
365    @Override
366    public boolean setLine1Number(String alphaTag, String number, Message onComplete) {
367        // FIXME: what to reply for Volte?
368        return false;
369    }
370
371    @Override
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
380    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
381    }
382
383    @Override
384    public void setCallForwardingOption(int commandInterfaceCFAction,
385            int commandInterfaceCFReason, String dialingNumber,
386            int timerSeconds, Message onComplete) {
387    }
388
389    @Override
390    public void getOutgoingCallerIdDisplay(Message onComplete) {
391        // FIXME: what to reply?
392        AsyncResult.forMessage(onComplete, null, null);
393        onComplete.sendToTarget();
394    }
395
396    @Override
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
405    public void getCallWaiting(Message onComplete) {
406        AsyncResult.forMessage(onComplete, null, null);
407        onComplete.sendToTarget();
408    }
409
410    @Override
411    public void setCallWaiting(boolean enable, Message onComplete) {
412        Rlog.e(LOG_TAG, "call waiting not supported");
413    }
414
415    @Override
416    public boolean getIccRecordsLoaded() {
417        return false;
418    }
419
420    @Override
421    public IccCard getIccCard() {
422        return null;
423    }
424
425    @Override
426    public void getAvailableNetworks(Message response) {
427    }
428
429    @Override
430    public void startNetworkScan(Message response) {
431    }
432
433    @Override
434    public void stopNetworkScan(Message response) {
435    }
436
437    @Override
438    public void setNetworkSelectionModeAutomatic(Message response) {
439    }
440
441    @Override
442    public void selectNetworkManually(OperatorInfo network, boolean persistSelection,
443            Message response) {
444    }
445
446    @Override
447    public void getDataCallList(Message response) {
448    }
449
450    public List<DataConnection> getCurrentDataConnectionList () {
451        return null;
452    }
453
454    @Override
455    public void updateServiceLocation() {
456    }
457
458    @Override
459    public void enableLocationUpdates() {
460    }
461
462    @Override
463    public void disableLocationUpdates() {
464    }
465
466    @Override
467    public boolean getDataRoamingEnabled() {
468        return false;
469    }
470
471    @Override
472    public void setDataRoamingEnabled(boolean enable) {
473    }
474
475    @Override
476    public boolean getDataEnabled() {
477        return false;
478    }
479
480    @Override
481    public void setDataEnabled(boolean enable) {
482    }
483
484
485    public boolean enableDataConnectivity() {
486        return false;
487    }
488
489    public boolean disableDataConnectivity() {
490        return false;
491    }
492
493    @Override
494    public boolean isDataAllowed() {
495        return false;
496    }
497
498    public void saveClirSetting(int commandInterfaceCLIRMode) {
499    }
500
501    @Override
502    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
503        return null;
504    }
505
506    @Override
507    public IccFileHandler getIccFileHandler(){
508        return null;
509    }
510
511    @Override
512    public void activateCellBroadcastSms(int activate, Message response) {
513        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
514    }
515
516    @Override
517    public void getCellBroadcastSmsConfig(Message response) {
518        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
519    }
520
521    @Override
522    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
523        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
524    }
525
526    //@Override
527    @Override
528    public boolean needsOtaServiceProvisioning() {
529        // FIXME: what's this for Volte?
530        return false;
531    }
532
533    //@Override
534    @Override
535    public LinkProperties getLinkProperties(String apnType) {
536        // FIXME: what's this for Volte?
537        return null;
538    }
539
540    @Override
541    protected void onUpdateIccAvailability() {
542    }
543
544    void updatePhoneState() {
545        PhoneConstants.State oldState = mState;
546
547        if (getRingingCall().isRinging()) {
548            mState = PhoneConstants.State.RINGING;
549        } else if (getForegroundCall().isIdle()
550                && getBackgroundCall().isIdle()) {
551            mState = PhoneConstants.State.IDLE;
552        } else {
553            mState = PhoneConstants.State.OFFHOOK;
554        }
555
556        if (mState != oldState) {
557            Rlog.d(LOG_TAG, " ^^^ new phone state: " + mState);
558            notifyPhoneStateChanged();
559        }
560    }
561}
562