Home | History | Annotate | Download | only in incallui
      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.incallui;
     18 
     19 import com.android.incallui.AudioModeProvider.AudioModeListener;
     20 import com.android.incallui.InCallPresenter.InCallState;
     21 import com.android.incallui.InCallPresenter.InCallStateListener;
     22 import com.android.incallui.InCallPresenter.IncomingCallListener;
     23 import com.android.services.telephony.common.AudioMode;
     24 import com.android.services.telephony.common.Call;
     25 import com.android.services.telephony.common.Call.Capabilities;
     26 
     27 import android.telephony.PhoneNumberUtils;
     28 
     29 /**
     30  * Logic for call buttons.
     31  */
     32 public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButtonUi>
     33         implements InCallStateListener, AudioModeListener, IncomingCallListener {
     34 
     35     private Call mCall;
     36     private boolean mAutomaticallyMuted = false;
     37     private boolean mPreviousMuteState = false;
     38 
     39     private boolean mShowGenericMerge = false;
     40     private boolean mShowManageConference = false;
     41 
     42     private InCallState mPreviousState = null;
     43 
     44     public CallButtonPresenter() {
     45     }
     46 
     47     @Override
     48     public void onUiReady(CallButtonUi ui) {
     49         super.onUiReady(ui);
     50 
     51         AudioModeProvider.getInstance().addListener(this);
     52 
     53         // register for call state changes last
     54         InCallPresenter.getInstance().addListener(this);
     55         InCallPresenter.getInstance().addIncomingCallListener(this);
     56     }
     57 
     58     @Override
     59     public void onUiUnready(CallButtonUi ui) {
     60         super.onUiUnready(ui);
     61 
     62         InCallPresenter.getInstance().removeListener(this);
     63         AudioModeProvider.getInstance().removeListener(this);
     64         InCallPresenter.getInstance().removeIncomingCallListener(this);
     65     }
     66 
     67     @Override
     68     public void onStateChange(InCallState state, CallList callList) {
     69 
     70         if (state == InCallState.OUTGOING) {
     71             mCall = callList.getOutgoingCall();
     72         } else if (state == InCallState.INCALL) {
     73             mCall = callList.getActiveOrBackgroundCall();
     74 
     75             // When connected to voice mail, automatically shows the dialpad.
     76             // (On previous releases we showed it when in-call shows up, before waiting for
     77             // OUTGOING.  We may want to do that once we start showing "Voice mail" label on
     78             // the dialpad too.)
     79             if (mPreviousState == InCallState.OUTGOING
     80                     && mCall != null && PhoneNumberUtils.isVoiceMailNumber(mCall.getNumber())) {
     81                 getUi().displayDialpad(true);
     82             }
     83         } else if (state == InCallState.INCOMING) {
     84             getUi().displayDialpad(false);
     85             mCall = null;
     86         } else {
     87             mCall = null;
     88         }
     89         updateUi(state, mCall);
     90 
     91         mPreviousState = state;
     92     }
     93 
     94     @Override
     95     public void onIncomingCall(InCallState state, Call call) {
     96         onStateChange(state, CallList.getInstance());
     97     }
     98 
     99     @Override
    100     public void onAudioMode(int mode) {
    101         if (getUi() != null) {
    102             getUi().setAudio(mode);
    103         }
    104     }
    105 
    106     @Override
    107     public void onSupportedAudioMode(int mask) {
    108         if (getUi() != null) {
    109             getUi().setSupportedAudio(mask);
    110         }
    111     }
    112 
    113     @Override
    114     public void onMute(boolean muted) {
    115         if (getUi() != null) {
    116             getUi().setMute(muted);
    117         }
    118     }
    119 
    120     public int getAudioMode() {
    121         return AudioModeProvider.getInstance().getAudioMode();
    122     }
    123 
    124     public int getSupportedAudio() {
    125         return AudioModeProvider.getInstance().getSupportedModes();
    126     }
    127 
    128     public void setAudioMode(int mode) {
    129 
    130         // TODO: Set a intermediate state in this presenter until we get
    131         // an update for onAudioMode().  This will make UI response immediate
    132         // if it turns out to be slow
    133 
    134         Log.d(this, "Sending new Audio Mode: " + AudioMode.toString(mode));
    135         CallCommandClient.getInstance().setAudioMode(mode);
    136     }
    137 
    138     /**
    139      * Function assumes that bluetooth is not supported.
    140      */
    141     public void toggleSpeakerphone() {
    142         // this function should not be called if bluetooth is available
    143         if (0 != (AudioMode.BLUETOOTH & getSupportedAudio())) {
    144 
    145             // It's clear the UI is wrong, so update the supported mode once again.
    146             Log.e(this, "toggling speakerphone not allowed when bluetooth supported.");
    147             getUi().setSupportedAudio(getSupportedAudio());
    148             return;
    149         }
    150 
    151         int newMode = AudioMode.SPEAKER;
    152 
    153         // if speakerphone is already on, change to wired/earpiece
    154         if (getAudioMode() == AudioMode.SPEAKER) {
    155             newMode = AudioMode.WIRED_OR_EARPIECE;
    156         }
    157 
    158         setAudioMode(newMode);
    159     }
    160 
    161     public void endCallClicked() {
    162         if (mCall == null) {
    163             return;
    164         }
    165 
    166         CallCommandClient.getInstance().disconnectCall(mCall.getCallId());
    167     }
    168 
    169     public void manageConferenceButtonClicked() {
    170         getUi().displayManageConferencePanel(true);
    171     }
    172 
    173     public void muteClicked(boolean checked) {
    174         Log.d(this, "turning on mute: " + checked);
    175 
    176         CallCommandClient.getInstance().mute(checked);
    177     }
    178 
    179     public void holdClicked(boolean checked) {
    180         if (mCall == null) {
    181             return;
    182         }
    183 
    184         Log.d(this, "holding: " + mCall.getCallId());
    185 
    186         CallCommandClient.getInstance().hold(mCall.getCallId(), checked);
    187     }
    188 
    189     public void mergeClicked() {
    190         CallCommandClient.getInstance().merge();
    191     }
    192 
    193     public void addCallClicked() {
    194         // Automatically mute the current call
    195         mAutomaticallyMuted = true;
    196         mPreviousMuteState = AudioModeProvider.getInstance().getMute();
    197         // Simulate a click on the mute button
    198         muteClicked(true);
    199 
    200         CallCommandClient.getInstance().addCall();
    201     }
    202 
    203     public void swapClicked() {
    204         CallCommandClient.getInstance().swap();
    205     }
    206 
    207     public void showDialpadClicked(boolean checked) {
    208         Log.v(this, "Show dialpad " + String.valueOf(checked));
    209         getUi().displayDialpad(checked);
    210         updateExtraButtonRow();
    211     }
    212 
    213     private void updateUi(InCallState state, Call call) {
    214         final CallButtonUi ui = getUi();
    215         if (ui == null) {
    216             return;
    217         }
    218 
    219         final boolean isEnabled = state.isConnectingOrConnected() &&
    220                 !state.isIncoming() && call != null;
    221 
    222         ui.setEnabled(isEnabled);
    223 
    224         Log.d(this, "Updating call UI for call: ", call);
    225 
    226         if (isEnabled) {
    227             Log.v(this, "Show hold ", call.can(Capabilities.SUPPORT_HOLD));
    228             Log.v(this, "Enable hold", call.can(Capabilities.HOLD));
    229             Log.v(this, "Show merge ", call.can(Capabilities.MERGE_CALLS));
    230             Log.v(this, "Show swap ", call.can(Capabilities.SWAP_CALLS));
    231             Log.v(this, "Show add call ", call.can(Capabilities.ADD_CALL));
    232             Log.v(this, "Show mute ", call.can(Capabilities.MUTE));
    233 
    234             final boolean canMerge = call.can(Capabilities.MERGE_CALLS);
    235             final boolean canAdd = call.can(Capabilities.ADD_CALL);
    236             final boolean isGenericConference = call.can(Capabilities.GENERIC_CONFERENCE);
    237 
    238 
    239             final boolean showMerge = !isGenericConference && canMerge;
    240 
    241             if (showMerge) {
    242                 ui.showMerge(true);
    243                 ui.showAddCall(false);
    244             } else {
    245                 ui.showMerge(false);
    246                 ui.showAddCall(true);
    247                 ui.enableAddCall(canAdd);
    248             }
    249 
    250             final boolean canHold = call.can(Capabilities.HOLD);
    251             final boolean canSwap = call.can(Capabilities.SWAP_CALLS);
    252             final boolean supportHold = call.can(Capabilities.SUPPORT_HOLD);
    253 
    254             if (canHold) {
    255                 ui.showHold(true);
    256                 ui.setHold(call.getState() == Call.State.ONHOLD);
    257                 ui.enableHold(true);
    258                 ui.showSwap(false);
    259             } else if (canSwap) {
    260                 ui.showHold(false);
    261                 ui.showSwap(true);
    262             } else {
    263                 // Neither "Hold" nor "Swap" is available.  This can happen for two
    264                 // reasons:
    265                 //   (1) this is a transient state on a device that *can*
    266                 //       normally hold or swap, or
    267                 //   (2) this device just doesn't have the concept of hold/swap.
    268                 //
    269                 // In case (1), show the "Hold" button in a disabled state.  In case
    270                 // (2), remove the button entirely.  (This means that the button row
    271                 // will only have 4 buttons on some devices.)
    272 
    273                 if (supportHold) {
    274                     ui.showHold(true);
    275                     ui.enableHold(false);
    276                     ui.setHold(call.getState() == Call.State.ONHOLD);
    277                     ui.showSwap(false);
    278                 } else {
    279                     ui.showHold(false);
    280                     ui.showSwap(false);
    281                 }
    282             }
    283 
    284             ui.enableMute(call.can(Capabilities.MUTE));
    285 
    286             // Finally, update the "extra button row": It's displayed above the
    287             // "End" button, but only if necessary.  Also, it's never displayed
    288             // while the dialpad is visible (since it would overlap.)
    289             //
    290             // The row contains two buttons:
    291             //
    292             // - "Manage conference" (used only on GSM devices)
    293             // - "Merge" button (used only on CDMA devices)
    294 
    295             mShowGenericMerge = isGenericConference && canMerge;
    296             mShowManageConference = (call.isConferenceCall() && !isGenericConference);
    297 
    298             updateExtraButtonRow();
    299         }
    300     }
    301 
    302     private void updateExtraButtonRow() {
    303         final boolean showExtraButtonRow = (mShowGenericMerge || mShowManageConference) &&
    304                 !getUi().isDialpadVisible();
    305 
    306         Log.d(this, "isGeneric: " + mShowGenericMerge);
    307         Log.d(this, "mShowManageConference : " + mShowManageConference);
    308         Log.d(this, "mShowGenericMerge: " + mShowGenericMerge);
    309         if (showExtraButtonRow) {
    310             if (mShowGenericMerge) {
    311                 getUi().showGenericMergeButton();
    312             } else if (mShowManageConference) {
    313                 getUi().showManageConferenceCallButton();
    314             }
    315         } else {
    316             getUi().hideExtraRow();
    317         }
    318     }
    319 
    320     public void refreshMuteState() {
    321         // Restore the previous mute state
    322         if (mAutomaticallyMuted &&
    323                 AudioModeProvider.getInstance().getMute() != mPreviousMuteState) {
    324             if (getUi() == null) {
    325                 return;
    326             }
    327             muteClicked(mPreviousMuteState);
    328         }
    329         mAutomaticallyMuted = false;
    330     }
    331 
    332     public interface CallButtonUi extends Ui {
    333         void setEnabled(boolean on);
    334         void setMute(boolean on);
    335         void enableMute(boolean enabled);
    336         void setHold(boolean on);
    337         void showHold(boolean show);
    338         void enableHold(boolean enabled);
    339         void showMerge(boolean show);
    340         void showSwap(boolean show);
    341         void showAddCall(boolean show);
    342         void enableAddCall(boolean enabled);
    343         void displayDialpad(boolean on);
    344         boolean isDialpadVisible();
    345         void setAudio(int mode);
    346         void setSupportedAudio(int mask);
    347         void showManageConferenceCallButton();
    348         void showGenericMergeButton();
    349         void hideExtraRow();
    350         void displayManageConferencePanel(boolean on);
    351     }
    352 }
    353