CallButtonFragment.java revision cda81c2ef1ba595c35ae1d4ad72c44f3443e08fd
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.incallui;
18
19import android.content.Context;
20import android.graphics.drawable.LayerDrawable;
21import android.os.Bundle;
22import android.telecomm.AudioState;
23import android.view.ContextThemeWrapper;
24import android.view.LayoutInflater;
25import android.view.Menu;
26import android.view.MenuItem;
27import android.view.View;
28import android.view.ViewGroup;
29import android.view.accessibility.AccessibilityEvent;
30import android.view.accessibility.AccessibilityManager;
31import android.widget.CompoundButton;
32import android.widget.ImageButton;
33import android.widget.PopupMenu;
34import android.widget.PopupMenu.OnDismissListener;
35import android.widget.PopupMenu.OnMenuItemClickListener;
36
37/**
38 * Fragment for call control buttons
39 */
40public class CallButtonFragment
41        extends BaseFragment<CallButtonPresenter, CallButtonPresenter.CallButtonUi>
42        implements CallButtonPresenter.CallButtonUi, OnMenuItemClickListener, OnDismissListener,
43        View.OnClickListener, CompoundButton.OnCheckedChangeListener {
44
45    private ImageButton mAudioButton;
46    private ImageButton mChangeToVoiceButton;
47    private ImageButton mMuteButton;
48    private ImageButton mShowDialpadButton;
49    private ImageButton mHoldButton;
50    private ImageButton mSwapButton;
51    private ImageButton mChangeToVideoButton;
52    private ImageButton mSwitchCameraButton;
53    private ImageButton mAddCallButton;
54    private ImageButton mMergeButton;
55    private ImageButton mPauseVideoButton;
56    private ImageButton mOverflowButton;
57
58    private PopupMenu mAudioModePopup;
59    private boolean mAudioModePopupVisible;
60    private PopupMenu mOverflowPopup;
61    private View mExtraRowButton;
62    private View mManageConferenceButton;
63    private View mGenericMergeButton;
64
65    private int mPrevAudioMode = 0;
66
67    // Constants for Drawable.setAlpha()
68    private static final int HIDDEN = 0;
69    private static final int VISIBLE = 255;
70
71    private boolean mIsEnabled;
72
73    @Override
74    CallButtonPresenter createPresenter() {
75        // TODO: find a cleaner way to include audio mode provider than having a singleton instance.
76        return new CallButtonPresenter();
77    }
78
79    @Override
80    CallButtonPresenter.CallButtonUi getUi() {
81        return this;
82    }
83
84    @Override
85    public void onCreate(Bundle savedInstanceState) {
86        super.onCreate(savedInstanceState);
87    }
88
89    @Override
90    public View onCreateView(LayoutInflater inflater, ViewGroup container,
91            Bundle savedInstanceState) {
92        final View parent = inflater.inflate(R.layout.call_button_fragment, container, false);
93
94        mExtraRowButton = parent.findViewById(R.id.extraButtonRow);
95
96        mManageConferenceButton = parent.findViewById(R.id.manageConferenceButton);
97        mManageConferenceButton.setOnClickListener(this);
98        mGenericMergeButton = parent.findViewById(R.id.cdmaMergeButton);
99        mGenericMergeButton.setOnClickListener(this);
100
101        mAudioButton = (ImageButton) parent.findViewById(R.id.audioButton);
102        mAudioButton.setOnClickListener(this);
103        mChangeToVoiceButton = (ImageButton) parent.findViewById(R.id.changeToVoiceButton);
104        mChangeToVoiceButton. setOnClickListener(this);
105        mMuteButton = (ImageButton) parent.findViewById(R.id.muteButton);
106        mMuteButton.setOnClickListener(this);
107        mShowDialpadButton = (ImageButton) parent.findViewById(R.id.dialpadButton);
108        mShowDialpadButton.setOnClickListener(this);
109        mHoldButton = (ImageButton) parent.findViewById(R.id.holdButton);
110        mHoldButton.setOnClickListener(this);
111        mSwapButton = (ImageButton) parent.findViewById(R.id.swapButton);
112        mSwapButton.setOnClickListener(this);
113        mChangeToVideoButton = (ImageButton) parent.findViewById(R.id.changeToVideoButton);
114        mChangeToVideoButton.setOnClickListener(this);
115        mSwitchCameraButton = (ImageButton) parent.findViewById(R.id.switchCameraButton);
116        mSwitchCameraButton.setOnClickListener(this);
117        mAddCallButton = (ImageButton) parent.findViewById(R.id.addButton);
118        mAddCallButton.setOnClickListener(this);
119        mMergeButton = (ImageButton) parent.findViewById(R.id.mergeButton);
120        mMergeButton.setOnClickListener(this);
121        mPauseVideoButton = (ImageButton) parent.findViewById(R.id.pauseVideoButton);
122        mPauseVideoButton.setOnClickListener(this);
123        mOverflowButton = (ImageButton) parent.findViewById(R.id.overflowButton);
124        mOverflowButton.setOnClickListener(this);
125
126        return parent;
127    }
128
129    @Override
130    public void onActivityCreated(Bundle savedInstanceState) {
131        super.onActivityCreated(savedInstanceState);
132
133        // set the buttons
134        updateAudioButtons(getPresenter().getSupportedAudio());
135    }
136
137    @Override
138    public void onResume() {
139        if (getPresenter() != null) {
140            getPresenter().refreshMuteState();
141        }
142        super.onResume();
143    }
144
145    @Override
146    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
147    }
148
149    @Override
150    public void onClick(View view) {
151        int id = view.getId();
152        Log.d(this, "onClick(View " + view + ", id " + id + ")...");
153
154        switch(id) {
155            case R.id.audioButton:
156                onAudioButtonClicked();
157                break;
158            case R.id.addButton:
159                getPresenter().addCallClicked();
160                break;
161            case R.id.changeToVoiceButton:
162                getPresenter().changeToVoiceClicked();
163                break;
164            case R.id.muteButton: {
165                final ImageButton button = (ImageButton) view;
166                getPresenter().muteClicked(!button.isSelected());
167                break;
168            }
169            case R.id.cdmaMergeButton:
170            case R.id.mergeButton:
171                getPresenter().mergeClicked();
172                break;
173            case R.id.holdButton: {
174                final ImageButton button = (ImageButton) view;
175                getPresenter().holdClicked(!button.isSelected());
176                break;
177            }
178            case R.id.swapButton:
179                getPresenter().swapClicked();
180                break;
181            case R.id.dialpadButton:
182                getPresenter().showDialpadClicked(!mShowDialpadButton.isSelected());
183                break;
184            case R.id.changeToVideoButton:
185                getPresenter().changeToVideoClicked();
186                break;
187            case R.id.switchCameraButton:
188                getPresenter().switchCameraClicked(
189                        mSwitchCameraButton.isSelected() /* useFrontFacingCamera */);
190                break;
191            case R.id.pauseVideoButton:
192                getPresenter().pauseVideoClicked(
193                        !mPauseVideoButton.isSelected() /* pause */);
194                break;
195            case R.id.overflowButton:
196                mOverflowPopup.show();
197                break;
198            case R.id.manageConferenceButton:
199                getPresenter().manageConferenceButtonClicked();
200                break;
201            default:
202                Log.wtf(this, "onClick: unexpected");
203                break;
204        }
205    }
206
207    @Override
208    public void setEnabled(boolean isEnabled) {
209        mIsEnabled = isEnabled;
210        View view = getView();
211        if (view.getVisibility() != View.VISIBLE) {
212            view.setVisibility(View.VISIBLE);
213        }
214
215        mAudioButton.setEnabled(isEnabled);
216        mChangeToVoiceButton.setEnabled(isEnabled);
217        mMuteButton.setEnabled(isEnabled);
218        mShowDialpadButton.setEnabled(isEnabled);
219        mHoldButton.setEnabled(isEnabled);
220        mSwapButton.setEnabled(isEnabled);
221        mChangeToVideoButton.setEnabled(isEnabled);
222        mSwitchCameraButton.setEnabled(isEnabled);
223        mAddCallButton.setEnabled(isEnabled);
224        mMergeButton.setEnabled(isEnabled);
225        mPauseVideoButton.setEnabled(isEnabled);
226        mOverflowButton.setEnabled(isEnabled);
227    }
228
229    @Override
230    public void setMute(boolean value) {
231        if (mMuteButton.isSelected() != value) {
232            mMuteButton.setSelected(value);
233            maybeSendAccessibilityEvent(mMuteButton, value ? R.string.accessibility_call_muted
234                    : R.string.accessibility_call_unmuted);
235        }
236    }
237
238    @Override
239    public void showAudioButton(boolean show) {
240        mAudioButton.setVisibility(show ? View.VISIBLE : View.GONE);
241    }
242
243    @Override
244    public void showChangeToVoiceButton(boolean show) {
245        mChangeToVoiceButton.setVisibility(show ? View.VISIBLE : View.GONE);
246    }
247
248    @Override
249    public void enableMute(boolean enabled) {
250        mMuteButton.setEnabled(enabled);
251    }
252
253    @Override
254    public void showDialpadButton(boolean show) {
255        mShowDialpadButton.setVisibility(show ? View.VISIBLE : View.GONE);
256    }
257
258    @Override
259    public void setHold(boolean value) {
260        if (mHoldButton.isSelected() != value) {
261            mHoldButton.setSelected(value);
262            maybeSendAccessibilityEvent(mHoldButton,
263                    value ? R.string.accessibility_call_put_on_hold :
264                            R.string.accessibility_call_removed_from_hold);
265        }
266    }
267
268    @Override
269    public void showHoldButton(boolean show) {
270        mHoldButton.setVisibility(show ? View.VISIBLE : View.GONE);
271    }
272
273    @Override
274    public void enableHold(boolean enabled) {
275        mHoldButton.setEnabled(enabled);
276    }
277
278    @Override
279    public void showSwapButton(boolean show) {
280        mSwapButton.setVisibility(show ? View.VISIBLE : View.GONE);
281    }
282
283    @Override
284    public void showChangeToVideoButton(boolean show) {
285        mChangeToVideoButton.setVisibility(show ? View.VISIBLE : View.GONE);
286    }
287
288    @Override
289    public void showSwitchCameraButton(boolean show) {
290        mSwitchCameraButton.setVisibility(show ? View.VISIBLE : View.GONE);
291    }
292
293    @Override
294    public void setSwitchCameraButton(boolean isBackFacingCamera) {
295        mSwitchCameraButton.setSelected(isBackFacingCamera);
296    }
297
298    @Override
299    public void showAddCallButton(boolean show) {
300        Log.d(this, "show Add call button: " + show);
301        mAddCallButton.setVisibility(show ? View.VISIBLE : View.GONE);
302    }
303
304    @Override
305    public void enableAddCall(boolean enabled) {
306        mAddCallButton.setEnabled(enabled);
307    }
308
309    @Override
310    public void showMergeButton(boolean show) {
311        mMergeButton.setVisibility(show ? View.VISIBLE : View.GONE);
312    }
313
314    @Override
315    public void showPauseVideoButton(boolean show) {
316        mPauseVideoButton.setVisibility(show ? View.VISIBLE : View.GONE);
317    }
318
319    @Override
320    public void setPauseVideoButton(boolean isPaused) {
321        mPauseVideoButton.setSelected(isPaused);
322    }
323
324    @Override
325    public void showOverflowButton(boolean show) {
326        mOverflowButton.setVisibility(show ? View.VISIBLE : View.GONE);
327    }
328
329    @Override
330    public void configureOverflowMenu(boolean showMergeMenuOption, boolean showAddMenuOption,
331            boolean showHoldMenuOption, boolean showSwapMenuOption) {
332        if (mOverflowPopup == null) {
333            final ContextThemeWrapper contextWrapper = new ContextThemeWrapper(getActivity(),
334                    R.style.InCallPopupMenuStyle);
335            mOverflowPopup = new PopupMenu(contextWrapper, mOverflowButton);
336            mOverflowPopup.getMenuInflater().inflate(R.menu.incall_overflow_menu,
337                    mOverflowPopup.getMenu());
338            mOverflowPopup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
339                @Override
340                public boolean onMenuItemClick(MenuItem item) {
341                    switch (item.getItemId()) {
342                        case R.id.overflow_merge_menu_item:
343                            getPresenter().mergeClicked();
344                            break;
345                        case R.id.overflow_add_menu_item:
346                            getPresenter().addCallClicked();
347                            break;
348                        case R.id.overflow_hold_menu_item:
349                            getPresenter().holdClicked(true /* checked */);
350                            break;
351                        case R.id.overflow_resume_menu_item:
352                            getPresenter().holdClicked(false /* checked */);
353                            break;
354                        case R.id.overflow_swap_menu_item:
355                            getPresenter().addCallClicked();
356                            break;
357                        default:
358                            Log.wtf(this, "onMenuItemClick: unexpected overflow menu click");
359                            break;
360                    }
361                    return true;
362                }
363            });
364            mOverflowPopup.setOnDismissListener(new OnDismissListener() {
365                @Override
366                public void onDismiss(PopupMenu popupMenu) {
367                    popupMenu.dismiss();
368                }
369            });
370        }
371
372        final Menu menu = mOverflowPopup.getMenu();
373        menu.findItem(R.id.overflow_merge_menu_item).setVisible(showMergeMenuOption);
374        menu.findItem(R.id.overflow_add_menu_item).setVisible(showAddMenuOption);
375        menu.findItem(R.id.overflow_hold_menu_item).setVisible(
376                showHoldMenuOption && !mHoldButton.isSelected());
377        menu.findItem(R.id.overflow_resume_menu_item).setVisible(
378                showHoldMenuOption && mHoldButton.isSelected());
379        menu.findItem(R.id.overflow_swap_menu_item).setVisible(showSwapMenuOption);
380
381        mOverflowButton.setEnabled(menu.hasVisibleItems());
382    }
383
384    @Override
385    public void setAudio(int mode) {
386        updateAudioButtons(getPresenter().getSupportedAudio());
387        refreshAudioModePopup();
388
389        if (mPrevAudioMode != mode) {
390            if (mPrevAudioMode != 0) {
391                int stringId = 0;
392                switch (mode) {
393                    case AudioState.ROUTE_EARPIECE:
394                        stringId = R.string.accessibility_earpiece_selected;
395                        break;
396                    case AudioState.ROUTE_BLUETOOTH:
397                        stringId = R.string.accessibility_bluetooth_headset_selected;
398                        break;
399                    case AudioState.ROUTE_WIRED_HEADSET:
400                        stringId = R.string.accessibility_wired_headset_selected;
401                        break;
402                    case AudioState.ROUTE_SPEAKER:
403                        stringId = R.string.accessibility_speakerphone_selected;
404                        break;
405                }
406                if (stringId != 0) {
407                    maybeSendAccessibilityEvent(mAudioButton, stringId);
408                }
409            }
410            mPrevAudioMode = mode;
411        }
412    }
413
414    @Override
415    public void setSupportedAudio(int modeMask) {
416        updateAudioButtons(modeMask);
417        refreshAudioModePopup();
418    }
419
420    @Override
421    public boolean onMenuItemClick(MenuItem item) {
422        Log.d(this, "- onMenuItemClick: " + item);
423        Log.d(this, "  id: " + item.getItemId());
424        Log.d(this, "  title: '" + item.getTitle() + "'");
425
426        int mode = AudioState.ROUTE_WIRED_OR_EARPIECE;
427
428        switch (item.getItemId()) {
429            case R.id.audio_mode_speaker:
430                mode = AudioState.ROUTE_SPEAKER;
431                break;
432            case R.id.audio_mode_earpiece:
433            case R.id.audio_mode_wired_headset:
434                // InCallAudioState.ROUTE_EARPIECE means either the handset earpiece,
435                // or the wired headset (if connected.)
436                mode = AudioState.ROUTE_WIRED_OR_EARPIECE;
437                break;
438            case R.id.audio_mode_bluetooth:
439                mode = AudioState.ROUTE_BLUETOOTH;
440                break;
441            default:
442                Log.e(this, "onMenuItemClick:  unexpected View ID " + item.getItemId()
443                        + " (MenuItem = '" + item + "')");
444                break;
445        }
446
447        getPresenter().setAudioMode(mode);
448
449        return true;
450    }
451
452    // PopupMenu.OnDismissListener implementation; see showAudioModePopup().
453    // This gets called when the PopupMenu gets dismissed for *any* reason, like
454    // the user tapping outside its bounds, or pressing Back, or selecting one
455    // of the menu items.
456    @Override
457    public void onDismiss(PopupMenu menu) {
458        Log.d(this, "- onDismiss: " + menu);
459        mAudioModePopupVisible = false;
460    }
461
462    /**
463     * Checks for supporting modes.  If bluetooth is supported, it uses the audio
464     * pop up menu.  Otherwise, it toggles the speakerphone.
465     */
466    private void onAudioButtonClicked() {
467        Log.d(this, "onAudioButtonClicked: " +
468                AudioState.audioRouteToString(getPresenter().getSupportedAudio()));
469
470        if (isSupported(AudioState.ROUTE_BLUETOOTH)) {
471            showAudioModePopup();
472        } else {
473            getPresenter().toggleSpeakerphone();
474        }
475    }
476
477    /**
478     * Refreshes the "Audio mode" popup if it's visible.  This is useful
479     * (for example) when a wired headset is plugged or unplugged,
480     * since we need to switch back and forth between the "earpiece"
481     * and "wired headset" items.
482     *
483     * This is safe to call even if the popup is already dismissed, or even if
484     * you never called showAudioModePopup() in the first place.
485     */
486    public void refreshAudioModePopup() {
487        if (mAudioModePopup != null && mAudioModePopupVisible) {
488            // Dismiss the previous one
489            mAudioModePopup.dismiss();  // safe even if already dismissed
490            // And bring up a fresh PopupMenu
491            showAudioModePopup();
492        }
493    }
494
495    /**
496     * Updates the audio button so that the appriopriate visual layers
497     * are visible based on the supported audio formats.
498     */
499    private void updateAudioButtons(int supportedModes) {
500        final boolean bluetoothSupported = isSupported(AudioState.ROUTE_BLUETOOTH);
501        final boolean speakerSupported = isSupported(AudioState.ROUTE_SPEAKER);
502
503        boolean audioButtonEnabled = false;
504        boolean audioButtonChecked = false;
505        boolean showMoreIndicator = false;
506
507        boolean showBluetoothIcon = false;
508        boolean showSpeakerphoneIcon = false;
509        boolean showHandsetIcon = false;
510
511        boolean showToggleIndicator = false;
512
513        if (bluetoothSupported) {
514            Log.d(this, "updateAudioButtons - popup menu mode");
515
516            audioButtonEnabled = true;
517            showMoreIndicator = true;
518            // The audio button is NOT a toggle in this state.  (And its
519            // setChecked() state is irrelevant since we completely hide the
520            // btn_compound_background layer anyway.)
521
522            // Update desired layers:
523            if (isAudio(AudioState.ROUTE_BLUETOOTH)) {
524                showBluetoothIcon = true;
525            } else if (isAudio(AudioState.ROUTE_SPEAKER)) {
526                showSpeakerphoneIcon = true;
527            } else {
528                showHandsetIcon = true;
529                // TODO: if a wired headset is plugged in, that takes precedence
530                // over the handset earpiece.  If so, maybe we should show some
531                // sort of "wired headset" icon here instead of the "handset
532                // earpiece" icon.  (Still need an asset for that, though.)
533            }
534        } else if (speakerSupported) {
535            Log.d(this, "updateAudioButtons - speaker toggle mode");
536
537            audioButtonEnabled = true;
538
539            // The audio button *is* a toggle in this state, and indicated the
540            // current state of the speakerphone.
541            audioButtonChecked = isAudio(AudioState.ROUTE_SPEAKER);
542
543            // update desired layers:
544            showToggleIndicator = true;
545            showSpeakerphoneIcon = true;
546        } else {
547            Log.d(this, "updateAudioButtons - disabled...");
548
549            // The audio button is a toggle in this state, but that's mostly
550            // irrelevant since it's always disabled and unchecked.
551            audioButtonEnabled = false;
552            audioButtonChecked = false;
553
554            // update desired layers:
555            showToggleIndicator = true;
556            showSpeakerphoneIcon = true;
557        }
558
559        // Finally, update it all!
560
561        Log.v(this, "audioButtonEnabled: " + audioButtonEnabled);
562        Log.v(this, "audioButtonChecked: " + audioButtonChecked);
563        Log.v(this, "showMoreIndicator: " + showMoreIndicator);
564        Log.v(this, "showBluetoothIcon: " + showBluetoothIcon);
565        Log.v(this, "showSpeakerphoneIcon: " + showSpeakerphoneIcon);
566        Log.v(this, "showHandsetIcon: " + showHandsetIcon);
567
568        // Only enable the audio button if the fragment is enabled.
569        mAudioButton.setEnabled(audioButtonEnabled && mIsEnabled);
570        mAudioButton.setSelected(audioButtonChecked);
571
572        final LayerDrawable layers = (LayerDrawable) mAudioButton.getBackground();
573        Log.d(this, "'layers' drawable: " + layers);
574
575        layers.findDrawableByLayerId(R.id.compoundBackgroundItem)
576                .setAlpha(showToggleIndicator ? VISIBLE : HIDDEN);
577
578        layers.findDrawableByLayerId(R.id.moreIndicatorItem)
579                .setAlpha(showMoreIndicator ? VISIBLE : HIDDEN);
580
581        layers.findDrawableByLayerId(R.id.bluetoothItem)
582                .setAlpha(showBluetoothIcon ? VISIBLE : HIDDEN);
583
584        layers.findDrawableByLayerId(R.id.handsetItem)
585                .setAlpha(showHandsetIcon ? VISIBLE : HIDDEN);
586
587        layers.findDrawableByLayerId(R.id.speakerphoneItem)
588                .setAlpha(showSpeakerphoneIcon ? VISIBLE : HIDDEN);
589
590    }
591
592    private void showAudioModePopup() {
593        Log.d(this, "showAudioPopup()...");
594
595        final ContextThemeWrapper contextWrapper = new ContextThemeWrapper(getActivity(),
596                R.style.InCallPopupMenuStyle);
597        mAudioModePopup = new PopupMenu(contextWrapper, mAudioButton /* anchorView */);
598        mAudioModePopup.getMenuInflater().inflate(R.menu.incall_audio_mode_menu,
599                mAudioModePopup.getMenu());
600        mAudioModePopup.setOnMenuItemClickListener(this);
601        mAudioModePopup.setOnDismissListener(this);
602
603        final Menu menu = mAudioModePopup.getMenu();
604
605        // TODO: Still need to have the "currently active" audio mode come
606        // up pre-selected (or focused?) with a blue highlight.  Still
607        // need exact visual design, and possibly framework support for this.
608        // See comments below for the exact logic.
609
610        final MenuItem speakerItem = menu.findItem(R.id.audio_mode_speaker);
611        speakerItem.setEnabled(isSupported(AudioState.ROUTE_SPEAKER));
612        // TODO: Show speakerItem as initially "selected" if
613        // speaker is on.
614
615        // We display *either* "earpiece" or "wired headset", never both,
616        // depending on whether a wired headset is physically plugged in.
617        final MenuItem earpieceItem = menu.findItem(R.id.audio_mode_earpiece);
618        final MenuItem wiredHeadsetItem = menu.findItem(R.id.audio_mode_wired_headset);
619
620        final boolean usingHeadset = isSupported(AudioState.ROUTE_WIRED_HEADSET);
621        earpieceItem.setVisible(!usingHeadset);
622        earpieceItem.setEnabled(!usingHeadset);
623        wiredHeadsetItem.setVisible(usingHeadset);
624        wiredHeadsetItem.setEnabled(usingHeadset);
625        // TODO: Show the above item (either earpieceItem or wiredHeadsetItem)
626        // as initially "selected" if speakerOn and
627        // bluetoothIndicatorOn are both false.
628
629        final MenuItem bluetoothItem = menu.findItem(R.id.audio_mode_bluetooth);
630        bluetoothItem.setEnabled(isSupported(AudioState.ROUTE_BLUETOOTH));
631        // TODO: Show bluetoothItem as initially "selected" if
632        // bluetoothIndicatorOn is true.
633
634        mAudioModePopup.show();
635
636        // Unfortunately we need to manually keep track of the popup menu's
637        // visiblity, since PopupMenu doesn't have an isShowing() method like
638        // Dialogs do.
639        mAudioModePopupVisible = true;
640    }
641
642    private boolean isSupported(int mode) {
643        return (mode == (getPresenter().getSupportedAudio() & mode));
644    }
645
646    private boolean isAudio(int mode) {
647        return (mode == getPresenter().getAudioMode());
648    }
649
650    @Override
651    public void displayDialpad(boolean value, boolean animate) {
652        mShowDialpadButton.setSelected(value);
653        if (getActivity() != null && getActivity() instanceof InCallActivity) {
654            ((InCallActivity) getActivity()).displayDialpad(value, animate);
655        }
656    }
657
658    @Override
659    public boolean isDialpadVisible() {
660        if (getActivity() != null && getActivity() instanceof InCallActivity) {
661            return ((InCallActivity) getActivity()).isDialpadVisible();
662        }
663        return false;
664    }
665
666    @Override
667    public void displayManageConferencePanel(boolean value) {
668        if (getActivity() != null && getActivity() instanceof InCallActivity) {
669            ((InCallActivity) getActivity()).displayManageConferencePanel(value);
670        }
671    }
672
673    @Override
674    public Context getContext() {
675        return getActivity();
676    }
677
678    @Override
679    public void showManageConferenceCallButton() {
680        mExtraRowButton.setVisibility(View.VISIBLE);
681        mManageConferenceButton.setVisibility(View.VISIBLE);
682        mGenericMergeButton.setVisibility(View.GONE);
683    }
684
685    @Override
686    public void showGenericMergeButton() {
687        mExtraRowButton.setVisibility(View.VISIBLE);
688        mManageConferenceButton.setVisibility(View.GONE);
689        mGenericMergeButton.setVisibility(View.VISIBLE);
690    }
691
692    @Override
693    public void hideExtraRow() {
694       mExtraRowButton.setVisibility(View.GONE);
695    }
696
697    private void maybeSendAccessibilityEvent(View view, int stringId) {
698        final Context context = getActivity();
699        AccessibilityManager manager =
700                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
701        if (manager != null && manager.isEnabled()) {
702            AccessibilityEvent e = AccessibilityEvent.obtain();
703            e.setSource(view);
704            e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
705            e.setClassName(getClass().getName());
706            e.setPackageName(context.getPackageName());
707            e.getText().add(context.getResources().getString(stringId));
708            manager.sendAccessibilityEvent(e);
709        }
710    }
711}
712