Home | History | Annotate | Download | only in sip
      1 /*
      2  * Copyright (C) 2010 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.sip;
     18 
     19 import android.content.Context;
     20 import android.os.AsyncResult;
     21 import android.os.Handler;
     22 import android.os.Message;
     23 import android.os.Registrant;
     24 import android.os.RegistrantList;
     25 import android.os.SystemProperties;
     26 import android.telephony.CellLocation;
     27 import android.telephony.ServiceState;
     28 import android.telephony.SignalStrength;
     29 import android.util.Log;
     30 
     31 import com.android.internal.telephony.Call;
     32 import com.android.internal.telephony.CallStateException;
     33 import com.android.internal.telephony.Connection;
     34 import com.android.internal.telephony.DataConnection;
     35 import com.android.internal.telephony.IccCard;
     36 import com.android.internal.telephony.IccFileHandler;
     37 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
     38 import com.android.internal.telephony.IccSmsInterfaceManager;
     39 import com.android.internal.telephony.MmiCode;
     40 import com.android.internal.telephony.Phone;
     41 import com.android.internal.telephony.PhoneBase;
     42 import com.android.internal.telephony.PhoneNotifier;
     43 import com.android.internal.telephony.PhoneSubInfo;
     44 import com.android.internal.telephony.TelephonyProperties;
     45 
     46 import java.util.ArrayList;
     47 import java.util.List;
     48 
     49 abstract class SipPhoneBase extends PhoneBase {
     50     private static final String LOG_TAG = "SipPhone";
     51 
     52     private RegistrantList mRingbackRegistrants = new RegistrantList();
     53     private State state = State.IDLE;
     54 
     55     public SipPhoneBase(Context context, PhoneNotifier notifier) {
     56         super(notifier, context, new SipCommandInterface(context), false);
     57     }
     58 
     59     public abstract Call getForegroundCall();
     60 
     61     public abstract Call getBackgroundCall();
     62 
     63     public abstract Call getRingingCall();
     64 
     65     void migrateFrom(SipPhoneBase from) {
     66         migrate(mRingbackRegistrants, from.mRingbackRegistrants);
     67         migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
     68         migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
     69         migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
     70         migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
     71         migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
     72         migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
     73         migrate(mMmiRegistrants, from.mMmiRegistrants);
     74         migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
     75         migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
     76     }
     77 
     78     static void migrate(RegistrantList to, RegistrantList from) {
     79         from.removeCleared();
     80         for (int i = 0, n = from.size(); i < n; i++) {
     81             to.add((Registrant) from.get(i));
     82         }
     83     }
     84 
     85     @Override
     86     public void registerForRingbackTone(Handler h, int what, Object obj) {
     87         mRingbackRegistrants.addUnique(h, what, obj);
     88     }
     89 
     90     @Override
     91     public void unregisterForRingbackTone(Handler h) {
     92         mRingbackRegistrants.remove(h);
     93     }
     94 
     95     protected void startRingbackTone() {
     96         AsyncResult result = new AsyncResult(null, new Boolean(true), null);
     97         mRingbackRegistrants.notifyRegistrants(result);
     98     }
     99 
    100     protected void stopRingbackTone() {
    101         AsyncResult result = new AsyncResult(null, new Boolean(false), null);
    102         mRingbackRegistrants.notifyRegistrants(result);
    103     }
    104 
    105     public ServiceState getServiceState() {
    106         // FIXME: we may need to provide this when data connectivity is lost
    107         // or when server is down
    108         ServiceState s = new ServiceState();
    109         s.setState(ServiceState.STATE_IN_SERVICE);
    110         return s;
    111     }
    112 
    113     public CellLocation getCellLocation() {
    114         return null;
    115     }
    116 
    117     public State getState() {
    118         return state;
    119     }
    120 
    121     public int getPhoneType() {
    122         return Phone.PHONE_TYPE_SIP;
    123     }
    124 
    125     public SignalStrength getSignalStrength() {
    126         return new SignalStrength();
    127     }
    128 
    129     public boolean getMessageWaitingIndicator() {
    130         return false;
    131     }
    132 
    133     public boolean getCallForwardingIndicator() {
    134         return false;
    135     }
    136 
    137     public List<? extends MmiCode> getPendingMmiCodes() {
    138         return new ArrayList<MmiCode>(0);
    139     }
    140 
    141     public DataState getDataConnectionState() {
    142         return DataState.DISCONNECTED;
    143     }
    144 
    145     public DataState getDataConnectionState(String apnType) {
    146         return DataState.DISCONNECTED;
    147     }
    148 
    149     public DataActivityState getDataActivityState() {
    150         return DataActivityState.NONE;
    151     }
    152 
    153     /**
    154      * Notify any interested party of a Phone state change {@link Phone.State}
    155      */
    156     void notifyPhoneStateChanged() {
    157         mNotifier.notifyPhoneState(this);
    158     }
    159 
    160     /**
    161      * Notify registrants of a change in the call state. This notifies changes in {@link Call.State}
    162      * Use this when changes in the precise call state are needed, else use notifyPhoneStateChanged.
    163      */
    164     void notifyPreciseCallStateChanged() {
    165         /* we'd love it if this was package-scoped*/
    166         super.notifyPreciseCallStateChangedP();
    167     }
    168 
    169     void notifyNewRingingConnection(Connection c) {
    170         super.notifyNewRingingConnectionP(c);
    171     }
    172 
    173     void notifyDisconnect(Connection cn) {
    174         mDisconnectRegistrants.notifyResult(cn);
    175     }
    176 
    177     void notifyUnknownConnection() {
    178         mUnknownConnectionRegistrants.notifyResult(this);
    179     }
    180 
    181     void notifySuppServiceFailed(SuppService code) {
    182         mSuppServiceFailedRegistrants.notifyResult(code);
    183     }
    184 
    185     void notifyServiceStateChanged(ServiceState ss) {
    186         super.notifyServiceStateChangedP(ss);
    187     }
    188 
    189     public void notifyCallForwardingIndicator() {
    190         mNotifier.notifyCallForwardingChanged(this);
    191     }
    192 
    193     public boolean canDial() {
    194         int serviceState = getServiceState().getState();
    195         Log.v(LOG_TAG, "canDial(): serviceState = " + serviceState);
    196         if (serviceState == ServiceState.STATE_POWER_OFF) return false;
    197 
    198         String disableCall = SystemProperties.get(
    199                 TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
    200         Log.v(LOG_TAG, "canDial(): disableCall = " + disableCall);
    201         if (disableCall.equals("true")) return false;
    202 
    203         Log.v(LOG_TAG, "canDial(): ringingCall: " + getRingingCall().getState());
    204         Log.v(LOG_TAG, "canDial(): foregndCall: " + getForegroundCall().getState());
    205         Log.v(LOG_TAG, "canDial(): backgndCall: " + getBackgroundCall().getState());
    206         return !getRingingCall().isRinging()
    207                 && (!getForegroundCall().getState().isAlive()
    208                     || !getBackgroundCall().getState().isAlive());
    209     }
    210 
    211     public boolean handleInCallMmiCommands(String dialString)
    212             throws CallStateException {
    213         return false;
    214     }
    215 
    216     boolean isInCall() {
    217         Call.State foregroundCallState = getForegroundCall().getState();
    218         Call.State backgroundCallState = getBackgroundCall().getState();
    219         Call.State ringingCallState = getRingingCall().getState();
    220 
    221        return (foregroundCallState.isAlive() || backgroundCallState.isAlive()
    222             || ringingCallState.isAlive());
    223     }
    224 
    225     public boolean handlePinMmi(String dialString) {
    226         return false;
    227     }
    228 
    229     public void sendUssdResponse(String ussdMessge) {
    230     }
    231 
    232     public void registerForSuppServiceNotification(
    233             Handler h, int what, Object obj) {
    234     }
    235 
    236     public void unregisterForSuppServiceNotification(Handler h) {
    237     }
    238 
    239     public void setRadioPower(boolean power) {
    240     }
    241 
    242     public String getVoiceMailNumber() {
    243         return null;
    244     }
    245 
    246     public String getVoiceMailAlphaTag() {
    247         return null;
    248     }
    249 
    250     public String getDeviceId() {
    251         return null;
    252     }
    253 
    254     public String getDeviceSvn() {
    255         return null;
    256     }
    257 
    258     public String getEsn() {
    259         Log.e(LOG_TAG, "[SipPhone] getEsn() is a CDMA method");
    260         return "0";
    261     }
    262 
    263     public String getMeid() {
    264         Log.e(LOG_TAG, "[SipPhone] getMeid() is a CDMA method");
    265         return "0";
    266     }
    267 
    268     public String getSubscriberId() {
    269         return null;
    270     }
    271 
    272     public String getIccSerialNumber() {
    273         return null;
    274     }
    275 
    276     public String getLine1Number() {
    277         return null;
    278     }
    279 
    280     public String getLine1AlphaTag() {
    281         return null;
    282     }
    283 
    284     public void setLine1Number(String alphaTag, String number, Message onComplete) {
    285         // FIXME: what to reply for SIP?
    286         AsyncResult.forMessage(onComplete, null, null);
    287         onComplete.sendToTarget();
    288     }
    289 
    290     public void setVoiceMailNumber(String alphaTag, String voiceMailNumber,
    291             Message onComplete) {
    292         // FIXME: what to reply for SIP?
    293         AsyncResult.forMessage(onComplete, null, null);
    294         onComplete.sendToTarget();
    295     }
    296 
    297     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
    298     }
    299 
    300     public void setCallForwardingOption(int commandInterfaceCFAction,
    301             int commandInterfaceCFReason, String dialingNumber,
    302             int timerSeconds, Message onComplete) {
    303     }
    304 
    305     public void getOutgoingCallerIdDisplay(Message onComplete) {
    306         // FIXME: what to reply?
    307         AsyncResult.forMessage(onComplete, null, null);
    308         onComplete.sendToTarget();
    309     }
    310 
    311     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
    312                                            Message onComplete) {
    313         // FIXME: what's this for SIP?
    314         AsyncResult.forMessage(onComplete, null, null);
    315         onComplete.sendToTarget();
    316     }
    317 
    318     public void getCallWaiting(Message onComplete) {
    319         AsyncResult.forMessage(onComplete, null, null);
    320         onComplete.sendToTarget();
    321     }
    322 
    323     public void setCallWaiting(boolean enable, Message onComplete) {
    324         Log.e(LOG_TAG, "call waiting not supported");
    325     }
    326 
    327     public boolean getIccRecordsLoaded() {
    328         return false;
    329     }
    330 
    331     public IccCard getIccCard() {
    332         return null;
    333     }
    334 
    335     public void getAvailableNetworks(Message response) {
    336     }
    337 
    338     public void setNetworkSelectionModeAutomatic(Message response) {
    339     }
    340 
    341     public void selectNetworkManually(
    342             com.android.internal.telephony.gsm.NetworkInfo network,
    343             Message response) {
    344     }
    345 
    346     public void getNeighboringCids(Message response) {
    347     }
    348 
    349     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
    350     }
    351 
    352     public void getDataCallList(Message response) {
    353     }
    354 
    355     public List<DataConnection> getCurrentDataConnectionList () {
    356         return null;
    357     }
    358 
    359     public void updateServiceLocation() {
    360     }
    361 
    362     public void enableLocationUpdates() {
    363     }
    364 
    365     public void disableLocationUpdates() {
    366     }
    367 
    368     public boolean getDataRoamingEnabled() {
    369         return false;
    370     }
    371 
    372     public void setDataRoamingEnabled(boolean enable) {
    373     }
    374 
    375     public boolean enableDataConnectivity() {
    376         return false;
    377     }
    378 
    379     public boolean disableDataConnectivity() {
    380         return false;
    381     }
    382 
    383     public boolean isDataConnectivityPossible() {
    384         return false;
    385     }
    386 
    387     boolean updateCurrentCarrierInProvider() {
    388         return false;
    389     }
    390 
    391     public void saveClirSetting(int commandInterfaceCLIRMode) {
    392     }
    393 
    394     public PhoneSubInfo getPhoneSubInfo(){
    395         return null;
    396     }
    397 
    398     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
    399         return null;
    400     }
    401 
    402     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
    403         return null;
    404     }
    405 
    406     public IccFileHandler getIccFileHandler(){
    407         return null;
    408     }
    409 
    410     public void activateCellBroadcastSms(int activate, Message response) {
    411         Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
    412     }
    413 
    414     public void getCellBroadcastSmsConfig(Message response) {
    415         Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
    416     }
    417 
    418     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
    419         Log.e(LOG_TAG, "Error! This functionality is not implemented for SIP.");
    420     }
    421 
    422     void updatePhoneState() {
    423         State oldState = state;
    424 
    425         if (getRingingCall().isRinging()) {
    426             state = State.RINGING;
    427         } else if (getForegroundCall().isIdle()
    428                 && getBackgroundCall().isIdle()) {
    429             state = State.IDLE;
    430         } else {
    431             state = State.OFFHOOK;
    432         }
    433 
    434         if (state != oldState) {
    435             Log.d(LOG_TAG, " ^^^ new phone state: " + state);
    436             notifyPhoneStateChanged();
    437         }
    438     }
    439 }
    440