Home | History | Annotate | Download | only in phone
      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 
     17 package com.android.phone;
     18 
     19 import android.bluetooth.IBluetoothHeadsetPhone;
     20 import android.content.Context;
     21 import android.os.RemoteException;
     22 import android.os.SystemProperties;
     23 import android.util.Log;
     24 
     25 import com.android.internal.telephony.CallManager;
     26 import com.android.internal.telephony.PhoneConstants;
     27 import com.android.phone.CallModeler.CallResult;
     28 import com.android.phone.NotificationMgr.StatusBarHelper;
     29 import com.android.services.telephony.common.Call;
     30 import com.android.services.telephony.common.ICallCommandService;
     31 
     32 /**
     33  * Service interface used by in-call ui to control phone calls using commands exposed as methods.
     34  * Instances of this class are handed to in-call UI via CallMonitorService.
     35  */
     36 class CallCommandService extends ICallCommandService.Stub {
     37     private static final String TAG = CallCommandService.class.getSimpleName();
     38     private static final boolean DBG =
     39             (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
     40 
     41     private final Context mContext;
     42     private final CallManager mCallManager;
     43     private final CallModeler mCallModeler;
     44     private final DTMFTonePlayer mDtmfTonePlayer;
     45     private final AudioRouter mAudioRouter;
     46 
     47     public CallCommandService(Context context, CallManager callManager, CallModeler callModeler,
     48             DTMFTonePlayer dtmfTonePlayer, AudioRouter audioRouter) {
     49         mContext = context;
     50         mCallManager = callManager;
     51         mCallModeler = callModeler;
     52         mDtmfTonePlayer = dtmfTonePlayer;
     53         mAudioRouter = audioRouter;
     54     }
     55 
     56     /**
     57      * TODO: Add a confirmation callback parameter.
     58      */
     59     @Override
     60     public void answerCall(int callId) {
     61         try {
     62             CallResult result = mCallModeler.getCallWithId(callId);
     63             if (result != null) {
     64                 PhoneUtils.answerCall(result.getConnection().getCall());
     65             }
     66         } catch (Exception e) {
     67             Log.e(TAG, "Error during answerCall().", e);
     68         }
     69     }
     70 
     71     /**
     72      * TODO: Add a confirmation callback parameter.
     73      */
     74     @Override
     75     public void rejectCall(Call call, boolean rejectWithMessage, String message) {
     76         try {
     77             int callId = Call.INVALID_CALL_ID;
     78             String phoneNumber = "";
     79             if (call != null) {
     80                 callId = call.getCallId();
     81                 phoneNumber = call.getNumber();
     82             }
     83             CallResult result = mCallModeler.getCallWithId(callId);
     84 
     85             if (result != null) {
     86                 phoneNumber = result.getConnection().getAddress();
     87 
     88                 Log.v(TAG, "Hanging up");
     89                 PhoneUtils.hangupRingingCall(result.getConnection().getCall());
     90             }
     91 
     92             if (rejectWithMessage && !phoneNumber.isEmpty()) {
     93                 RejectWithTextMessageManager.rejectCallWithMessage(phoneNumber, message);
     94             }
     95         } catch (Exception e) {
     96             Log.e(TAG, "Error during rejectCall().", e);
     97         }
     98     }
     99 
    100     @Override
    101     public void disconnectCall(int callId) {
    102         try {
    103             CallResult result = mCallModeler.getCallWithId(callId);
    104             if (DBG) Log.d(TAG, "disconnectCall " + result.getCall());
    105 
    106             if (result != null) {
    107                 int state = result.getCall().getState();
    108                 if (Call.State.ACTIVE == state ||
    109                         Call.State.ONHOLD == state ||
    110                         Call.State.DIALING == state) {
    111                     result.getConnection().getCall().hangup();
    112                 } else if (Call.State.CONFERENCED == state) {
    113                     result.getConnection().hangup();
    114                 }
    115             }
    116         } catch (Exception e) {
    117             Log.e(TAG, "Error during disconnectCall().", e);
    118         }
    119     }
    120 
    121     @Override
    122     public void separateCall(int callId) {
    123         try {
    124             CallResult result = mCallModeler.getCallWithId(callId);
    125             if (DBG) Log.d(TAG, "disconnectCall " + result.getCall());
    126 
    127             if (result != null) {
    128                 int state = result.getCall().getState();
    129                 if (Call.State.CONFERENCED == state) {
    130                     result.getConnection().separate();
    131                 }
    132             }
    133         } catch (Exception e) {
    134             Log.e(TAG, "Error trying to separate call.", e);
    135         }
    136     }
    137 
    138     @Override
    139     public void hold(int callId, boolean hold) {
    140         try {
    141             CallResult result = mCallModeler.getCallWithId(callId);
    142             if (result != null) {
    143                 int state = result.getCall().getState();
    144                 if (hold && Call.State.ACTIVE == state) {
    145                     PhoneUtils.switchHoldingAndActive(mCallManager.getFirstActiveBgCall());
    146                 } else if (!hold && Call.State.ONHOLD == state) {
    147                     PhoneUtils.switchHoldingAndActive(result.getConnection().getCall());
    148                 }
    149             }
    150         } catch (Exception e) {
    151             Log.e(TAG, "Error trying to place call on hold.", e);
    152         }
    153     }
    154 
    155     @Override
    156     public void merge() {
    157         if (PhoneUtils.okToMergeCalls(mCallManager)) {
    158             PhoneUtils.mergeCalls(mCallManager);
    159         }
    160     }
    161 
    162     @Override
    163     public void addCall() {
    164         // start new call checks okToAddCall() already
    165         PhoneUtils.startNewCall(mCallManager);
    166     }
    167 
    168 
    169     @Override
    170     public void swap() {
    171         try {
    172             PhoneUtils.swap();
    173         } catch (Exception e) {
    174             Log.e(TAG, "Error during swap().", e);
    175         }
    176     }
    177 
    178     @Override
    179     public void mute(boolean onOff) {
    180         try {
    181             PhoneUtils.setMute(onOff);
    182         } catch (Exception e) {
    183             Log.e(TAG, "Error during mute().", e);
    184         }
    185     }
    186 
    187     @Override
    188     public void speaker(boolean onOff) {
    189         try {
    190             PhoneUtils.turnOnSpeaker(mContext, onOff, true);
    191         } catch (Exception e) {
    192             Log.e(TAG, "Error during speaker().", e);
    193         }
    194     }
    195 
    196     @Override
    197     public void playDtmfTone(char digit, boolean timedShortTone) {
    198         try {
    199             mDtmfTonePlayer.playDtmfTone(digit, timedShortTone);
    200         } catch (Exception e) {
    201             Log.e(TAG, "Error playing DTMF tone.", e);
    202         }
    203     }
    204 
    205     @Override
    206     public void stopDtmfTone() {
    207         try {
    208             mDtmfTonePlayer.stopDtmfTone();
    209         } catch (Exception e) {
    210             Log.e(TAG, "Error stopping DTMF tone.", e);
    211         }
    212     }
    213 
    214     @Override
    215     public void setAudioMode(int mode) {
    216         try {
    217             mAudioRouter.setAudioMode(mode);
    218         } catch (Exception e) {
    219             Log.e(TAG, "Error setting the audio mode.", e);
    220         }
    221     }
    222 
    223     @Override
    224     public void postDialCancel(int callId) throws RemoteException {
    225         final CallResult result = mCallModeler.getCallWithId(callId);
    226         if (result != null) {
    227             result.getConnection().cancelPostDial();
    228         }
    229     }
    230 
    231     @Override
    232     public void postDialWaitContinue(int callId) throws RemoteException {
    233         final CallResult result = mCallModeler.getCallWithId(callId);
    234         if (result != null) {
    235             result.getConnection().proceedAfterWaitChar();
    236         }
    237     }
    238 
    239     @Override
    240     public void setSystemBarNavigationEnabled(boolean enable) {
    241         try {
    242             final StatusBarHelper statusBarHelper = PhoneGlobals.getInstance().notificationMgr.
    243                     statusBarHelper;
    244             statusBarHelper.enableSystemBarNavigation(enable);
    245             statusBarHelper.enableExpandedView(enable);
    246         } catch (Exception e) {
    247             Log.e(TAG, "Error enabling or disabling system bar navigation", e);
    248         }
    249     }
    250 
    251 }
    252