ImsPhoneBase.java revision 75ba09a17a669f4906268088a769836aa87d8241
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.telephony.CellInfo;
27import android.telephony.CellLocation;
28import android.telephony.ServiceState;
29import android.telephony.SignalStrength;
30import android.telephony.Rlog;
31import android.util.Pair;
32
33import com.android.internal.telephony.Call;
34import com.android.internal.telephony.Connection;
35import com.android.internal.telephony.dataconnection.DataConnection;
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.uicc.IccFileHandler;
45
46import java.util.ArrayList;
47import java.util.List;
48
49abstract class ImsPhoneBase extends Phone {
50    private static final String LOG_TAG = "ImsPhoneBase";
51
52    private RegistrantList mRingbackRegistrants = new RegistrantList();
53    private RegistrantList mOnHoldRegistrants = new RegistrantList();
54    private RegistrantList mTtyModeReceivedRegistrants = new RegistrantList();
55    private PhoneConstants.State mState = PhoneConstants.State.IDLE;
56
57    public ImsPhoneBase(String name, Context context, PhoneNotifier notifier) {
58        super(name, notifier, context, new ImsPhoneCommandInterface(context), false);
59    }
60
61    @Override
62    public void migrateFrom(Phone from) {
63        super.migrateFrom(from);
64        migrate(mRingbackRegistrants, ((ImsPhoneBase)from).mRingbackRegistrants);
65    }
66
67    @Override
68    public void registerForRingbackTone(Handler h, int what, Object obj) {
69        mRingbackRegistrants.addUnique(h, what, obj);
70    }
71
72    @Override
73    public void unregisterForRingbackTone(Handler h) {
74        mRingbackRegistrants.remove(h);
75    }
76
77    @Override
78    public void startRingbackTone() {
79        AsyncResult result = new AsyncResult(null, Boolean.TRUE, null);
80        mRingbackRegistrants.notifyRegistrants(result);
81    }
82
83    @Override
84    public void stopRingbackTone() {
85        AsyncResult result = new AsyncResult(null, Boolean.FALSE, null);
86        mRingbackRegistrants.notifyRegistrants(result);
87    }
88
89    @Override
90    public void registerForOnHoldTone(Handler h, int what, Object obj) {
91        mOnHoldRegistrants.addUnique(h, what, obj);
92    }
93
94    @Override
95    public void unregisterForOnHoldTone(Handler h) {
96        mOnHoldRegistrants.remove(h);
97    }
98
99    /**
100     * Signals all registrants that the remote hold tone should be started for a connection.
101     *
102     * @param cn The connection.
103     */
104    protected void startOnHoldTone(Connection cn) {
105        Pair<Connection, Boolean> result = new Pair<Connection, Boolean>(cn, Boolean.TRUE);
106        mOnHoldRegistrants.notifyRegistrants(new AsyncResult(null, result, null));
107    }
108
109    /**
110     * Signals all registrants that the remote hold tone should be stopped for a connection.
111     *
112     * @param cn The connection.
113     */
114    protected void stopOnHoldTone(Connection cn) {
115        Pair<Connection, Boolean> result = new Pair<Connection, Boolean>(cn, Boolean.FALSE);
116        mOnHoldRegistrants.notifyRegistrants(new AsyncResult(null, result, null));
117    }
118
119    @Override
120    public void registerForTtyModeReceived(Handler h, int what, Object obj){
121        mTtyModeReceivedRegistrants.addUnique(h, what, obj);
122    }
123
124    @Override
125    public void unregisterForTtyModeReceived(Handler h) {
126        mTtyModeReceivedRegistrants.remove(h);
127    }
128
129    public void onTtyModeReceived(int mode) {
130        AsyncResult result = new AsyncResult(null, Integer.valueOf(mode), null);
131        mTtyModeReceivedRegistrants.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.setVoiceRegState(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    public 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    public void notifyPreciseCallStateChanged() {
215        /* we'd love it if this was package-scoped*/
216        super.notifyPreciseCallStateChangedP();
217    }
218
219    public void notifyDisconnect(Connection cn) {
220        mDisconnectRegistrants.notifyResult(cn);
221    }
222
223    void notifyUnknownConnection() {
224        mUnknownConnectionRegistrants.notifyResult(this);
225    }
226
227    void notifySuppServiceFailed(SuppService code) {
228        mSuppServiceFailedRegistrants.notifyResult(code);
229    }
230
231    void notifyServiceStateChanged(ServiceState ss) {
232        super.notifyServiceStateChangedP(ss);
233    }
234
235    @Override
236    public void notifyCallForwardingIndicator() {
237        mNotifier.notifyCallForwardingChanged(this);
238    }
239
240    public boolean canDial() {
241        int serviceState = getServiceState().getState();
242        Rlog.v(LOG_TAG, "canDial(): serviceState = " + serviceState);
243        if (serviceState == ServiceState.STATE_POWER_OFF) return false;
244
245        String disableCall = SystemProperties.get(
246                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
247        Rlog.v(LOG_TAG, "canDial(): disableCall = " + disableCall);
248        if (disableCall.equals("true")) return false;
249
250        Rlog.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState());
251        Rlog.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState());
252        Rlog.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState());
253        return !getRingingCall().isRinging()
254                && (!getForegroundCall().getState().isAlive()
255                    || !getBackgroundCall().getState().isAlive());
256    }
257
258    @Override
259    public boolean handleInCallMmiCommands(String dialString) {
260        return false;
261    }
262
263    boolean isInCall() {
264        Call.State foregroundCallState = getForegroundCall().getState();
265        Call.State backgroundCallState = getBackgroundCall().getState();
266        Call.State ringingCallState = getRingingCall().getState();
267
268       return (foregroundCallState.isAlive() || backgroundCallState.isAlive()
269               || ringingCallState.isAlive());
270    }
271
272    @Override
273    public boolean handlePinMmi(String dialString) {
274        return false;
275    }
276
277    @Override
278    public void sendUssdResponse(String ussdMessge) {
279    }
280
281    @Override
282    public void registerForSuppServiceNotification(
283            Handler h, int what, Object obj) {
284    }
285
286    @Override
287    public void unregisterForSuppServiceNotification(Handler h) {
288    }
289
290    @Override
291    public void setRadioPower(boolean power) {
292    }
293
294    @Override
295    public String getVoiceMailNumber() {
296        return null;
297    }
298
299    @Override
300    public String getVoiceMailAlphaTag() {
301        return null;
302    }
303
304    @Override
305    public String getDeviceId() {
306        return null;
307    }
308
309    @Override
310    public String getDeviceSvn() {
311        return null;
312    }
313
314    @Override
315    public String getImei() {
316        return null;
317    }
318
319    @Override
320    public String getEsn() {
321        Rlog.e(LOG_TAG, "[VoltePhone] getEsn() is a CDMA method");
322        return "0";
323    }
324
325    @Override
326    public String getMeid() {
327        Rlog.e(LOG_TAG, "[VoltePhone] getMeid() is a CDMA method");
328        return "0";
329    }
330
331    @Override
332    public String getSubscriberId() {
333        return null;
334    }
335
336    @Override
337    public String getGroupIdLevel1() {
338        return null;
339    }
340
341    @Override
342    public String getGroupIdLevel2() {
343        return null;
344    }
345
346    @Override
347    public String getIccSerialNumber() {
348        return null;
349    }
350
351    @Override
352    public String getLine1Number() {
353        return null;
354    }
355
356    @Override
357    public String getLine1AlphaTag() {
358        return null;
359    }
360
361    @Override
362    public boolean setLine1Number(String alphaTag, String number, Message onComplete) {
363        // FIXME: what to reply for Volte?
364        return false;
365    }
366
367    @Override
368    public void setVoiceMailNumber(String alphaTag, String voiceMailNumber,
369            Message onComplete) {
370        // FIXME: what to reply for Volte?
371        AsyncResult.forMessage(onComplete, null, null);
372        onComplete.sendToTarget();
373    }
374
375    @Override
376    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
377    }
378
379    @Override
380    public void setCallForwardingOption(int commandInterfaceCFAction,
381            int commandInterfaceCFReason, String dialingNumber,
382            int timerSeconds, Message onComplete) {
383    }
384
385    @Override
386    public void getOutgoingCallerIdDisplay(Message onComplete) {
387        // FIXME: what to reply?
388        AsyncResult.forMessage(onComplete, null, null);
389        onComplete.sendToTarget();
390    }
391
392    @Override
393    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
394            Message onComplete) {
395        // FIXME: what's this for Volte?
396        AsyncResult.forMessage(onComplete, null, null);
397        onComplete.sendToTarget();
398    }
399
400    @Override
401    public void getCallWaiting(Message onComplete) {
402        AsyncResult.forMessage(onComplete, null, null);
403        onComplete.sendToTarget();
404    }
405
406    @Override
407    public void setCallWaiting(boolean enable, Message onComplete) {
408        Rlog.e(LOG_TAG, "call waiting not supported");
409    }
410
411    @Override
412    public boolean getIccRecordsLoaded() {
413        return false;
414    }
415
416    @Override
417    public IccCard getIccCard() {
418        return null;
419    }
420
421    @Override
422    public void getAvailableNetworks(Message response) {
423    }
424
425    @Override
426    public void setNetworkSelectionModeAutomatic(Message response) {
427    }
428
429    @Override
430    public void selectNetworkManually(OperatorInfo network, boolean persistSelection,
431            Message response) {
432    }
433
434    @Override
435    public void getNeighboringCids(Message response) {
436    }
437
438    @Override
439    public void getDataCallList(Message response) {
440    }
441
442    public List<DataConnection> getCurrentDataConnectionList () {
443        return null;
444    }
445
446    @Override
447    public void updateServiceLocation() {
448    }
449
450    @Override
451    public void enableLocationUpdates() {
452    }
453
454    @Override
455    public void disableLocationUpdates() {
456    }
457
458    @Override
459    public boolean getDataRoamingEnabled() {
460        return false;
461    }
462
463    @Override
464    public void setDataRoamingEnabled(boolean enable) {
465    }
466
467    @Override
468    public boolean getDataEnabled() {
469        return false;
470    }
471
472    @Override
473    public void setDataEnabled(boolean enable) {
474    }
475
476
477    public boolean enableDataConnectivity() {
478        return false;
479    }
480
481    public boolean disableDataConnectivity() {
482        return false;
483    }
484
485    @Override
486    public boolean isDataConnectivityPossible() {
487        return false;
488    }
489
490    public void saveClirSetting(int commandInterfaceCLIRMode) {
491    }
492
493    @Override
494    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
495        return null;
496    }
497
498    @Override
499    public IccFileHandler getIccFileHandler(){
500        return null;
501    }
502
503    @Override
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
509    public void getCellBroadcastSmsConfig(Message response) {
510        Rlog.e(LOG_TAG, "Error! This functionality is not implemented for Volte.");
511    }
512
513    @Override
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
520    public boolean needsOtaServiceProvisioning() {
521        // FIXME: what's this for Volte?
522        return false;
523    }
524
525    //@Override
526    @Override
527    public LinkProperties getLinkProperties(String apnType) {
528        // FIXME: what's this for Volte?
529        return null;
530    }
531
532    @Override
533    protected void onUpdateIccAvailability() {
534    }
535
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