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