diff options
Diffstat (limited to 'java/com/android/incallui/incall/impl/ButtonController.java')
-rw-r--r-- | java/com/android/incallui/incall/impl/ButtonController.java | 584 |
1 files changed, 584 insertions, 0 deletions
diff --git a/java/com/android/incallui/incall/impl/ButtonController.java b/java/com/android/incallui/incall/impl/ButtonController.java new file mode 100644 index 000000000..8c113649d --- /dev/null +++ b/java/com/android/incallui/incall/impl/ButtonController.java @@ -0,0 +1,584 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.incallui.incall.impl; + +import android.support.annotation.CallSuper; +import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; +import android.telecom.CallAudioState; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import com.android.dialer.common.Assert; +import com.android.incallui.incall.impl.CheckableLabeledButton.OnCheckedChangeListener; +import com.android.incallui.incall.protocol.InCallButtonIds; +import com.android.incallui.incall.protocol.InCallButtonUiDelegate; +import com.android.incallui.incall.protocol.InCallScreenDelegate; + +/** Manages a single button. */ +interface ButtonController { + + boolean isEnabled(); + + void setEnabled(boolean isEnabled); + + boolean isAllowed(); + + void setAllowed(boolean isAllowed); + + void setChecked(boolean isChecked); + + @InCallButtonIds + int getInCallButtonId(); + + void setButton(CheckableLabeledButton button); + + final class Controllers { + + private static void resetButton(CheckableLabeledButton button) { + if (button != null) { + button.setOnCheckedChangeListener(null); + button.setOnClickListener(null); + } + } + } + + abstract class CheckableButtonController implements ButtonController, OnCheckedChangeListener { + + @NonNull protected final InCallButtonUiDelegate delegate; + @InCallButtonIds protected final int buttonId; + @StringRes protected final int checkedDescription; + @StringRes protected final int uncheckedDescription; + protected boolean isEnabled; + protected boolean isAllowed; + protected boolean isChecked; + protected CheckableLabeledButton button; + + protected CheckableButtonController( + @NonNull InCallButtonUiDelegate delegate, + @InCallButtonIds int buttonId, + @StringRes int checkedContentDescription, + @StringRes int uncheckedContentDescription) { + Assert.isNotNull(delegate); + this.delegate = delegate; + this.buttonId = buttonId; + this.checkedDescription = checkedContentDescription; + this.uncheckedDescription = uncheckedContentDescription; + } + + @Override + public boolean isEnabled() { + return isEnabled; + } + + @Override + public void setEnabled(boolean isEnabled) { + this.isEnabled = isEnabled; + if (button != null) { + button.setEnabled(isEnabled); + } + } + + @Override + public boolean isAllowed() { + return isAllowed; + } + + @Override + public void setAllowed(boolean isAllowed) { + this.isAllowed = isAllowed; + if (button != null) { + button.setVisibility(isAllowed ? View.VISIBLE : View.INVISIBLE); + } + } + + @Override + public void setChecked(boolean isChecked) { + this.isChecked = isChecked; + if (button != null) { + button.setChecked(isChecked); + } + } + + @Override + @InCallButtonIds + public int getInCallButtonId() { + return buttonId; + } + + @Override + @CallSuper + public void setButton(CheckableLabeledButton button) { + Controllers.resetButton(this.button); + + this.button = button; + if (button != null) { + button.setEnabled(isEnabled); + button.setVisibility(isAllowed ? View.VISIBLE : View.INVISIBLE); + button.setChecked(isChecked); + button.setOnClickListener(null); + button.setOnCheckedChangeListener(this); + button.setContentDescription( + button.getContext().getText(isChecked ? checkedDescription : uncheckedDescription)); + button.setShouldShowMoreIndicator(false); + } + } + + @Override + public void onCheckedChanged(CheckableLabeledButton checkableLabeledButton, boolean isChecked) { + button.setContentDescription( + button.getContext().getText(isChecked ? checkedDescription : uncheckedDescription)); + doCheckedChanged(isChecked); + } + + protected abstract void doCheckedChanged(boolean isChecked); + } + + abstract class SimpleCheckableButtonController extends CheckableButtonController { + + @StringRes private final int label; + @DrawableRes private final int icon; + + protected SimpleCheckableButtonController( + @NonNull InCallButtonUiDelegate delegate, + @InCallButtonIds int buttonId, + @StringRes int checkedContentDescription, + @StringRes int uncheckedContentDescription, + @StringRes int label, + @DrawableRes int icon) { + super( + delegate, + buttonId, + checkedContentDescription == 0 ? label : checkedContentDescription, + uncheckedContentDescription == 0 ? label : uncheckedContentDescription); + this.label = label; + this.icon = icon; + } + + @Override + @CallSuper + public void setButton(CheckableLabeledButton button) { + super.setButton(button); + if (button != null) { + button.setLabelText(label); + button.setIconDrawable(icon); + } + } + } + + abstract class NonCheckableButtonController implements ButtonController, OnClickListener { + + protected final InCallButtonUiDelegate delegate; + @InCallButtonIds protected final int buttonId; + @StringRes protected final int contentDescription; + protected boolean isEnabled; + protected boolean isAllowed; + protected CheckableLabeledButton button; + + protected NonCheckableButtonController( + InCallButtonUiDelegate delegate, + @InCallButtonIds int buttonId, + @StringRes int contentDescription) { + this.delegate = delegate; + this.buttonId = buttonId; + this.contentDescription = contentDescription; + } + + @Override + public boolean isEnabled() { + return isEnabled; + } + + @Override + public void setEnabled(boolean isEnabled) { + this.isEnabled = isEnabled; + if (button != null) { + button.setEnabled(isEnabled); + } + } + + @Override + public boolean isAllowed() { + return isAllowed; + } + + @Override + public void setAllowed(boolean isAllowed) { + this.isAllowed = isAllowed; + if (button != null) { + button.setVisibility(isAllowed ? View.VISIBLE : View.INVISIBLE); + } + } + + @Override + public void setChecked(boolean isChecked) { + Assert.fail(); + } + + @Override + @InCallButtonIds + public int getInCallButtonId() { + return buttonId; + } + + @Override + @CallSuper + public void setButton(CheckableLabeledButton button) { + Controllers.resetButton(this.button); + + this.button = button; + if (button != null) { + button.setEnabled(isEnabled); + button.setVisibility(isAllowed ? View.VISIBLE : View.INVISIBLE); + button.setChecked(false); + button.setOnCheckedChangeListener(null); + button.setOnClickListener(this); + button.setContentDescription(button.getContext().getText(contentDescription)); + button.setShouldShowMoreIndicator(false); + } + } + } + + abstract class SimpleNonCheckableButtonController extends NonCheckableButtonController { + + @StringRes private final int label; + @DrawableRes private final int icon; + + protected SimpleNonCheckableButtonController( + InCallButtonUiDelegate delegate, + @InCallButtonIds int buttonId, + @StringRes int contentDescription, + @StringRes int label, + @DrawableRes int icon) { + super(delegate, buttonId, contentDescription == 0 ? label : contentDescription); + this.label = label; + this.icon = icon; + } + + @Override + @CallSuper + public void setButton(CheckableLabeledButton button) { + super.setButton(button); + if (button != null) { + button.setLabelText(label); + button.setIconDrawable(icon); + } + } + } + + class MuteButtonController extends SimpleCheckableButtonController { + + public MuteButtonController(InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_MUTE, + R.string.incall_content_description_muted, + R.string.incall_content_description_unmuted, + R.string.incall_label_mute, + R.drawable.quantum_ic_mic_off_white_36); + } + + @Override + public void doCheckedChanged(boolean isChecked) { + delegate.muteClicked(isChecked, true /* clickedByUser */); + } + } + + class SpeakerButtonController + implements ButtonController, OnCheckedChangeListener, OnClickListener { + + @NonNull private final InCallButtonUiDelegate delegate; + private boolean isEnabled; + private boolean isAllowed; + private boolean isChecked; + private CheckableLabeledButton button; + + @StringRes private int label = R.string.incall_label_speaker; + @DrawableRes private int icon = R.drawable.quantum_ic_volume_up_white_36; + private boolean checkable; + private CharSequence contentDescription; + private CharSequence checkedContentDescription; + private CharSequence uncheckedContentDescription; + + public SpeakerButtonController(@NonNull InCallButtonUiDelegate delegate) { + this.delegate = delegate; + } + + @Override + public boolean isEnabled() { + return isEnabled; + } + + @Override + public void setEnabled(boolean isEnabled) { + this.isEnabled = isEnabled; + if (button != null) { + button.setEnabled(isEnabled && isAllowed); + } + } + + @Override + public boolean isAllowed() { + return isAllowed; + } + + @Override + public void setAllowed(boolean isAllowed) { + this.isAllowed = isAllowed; + if (button != null) { + button.setEnabled(isEnabled && isAllowed); + } + } + + @Override + public void setChecked(boolean isChecked) { + this.isChecked = isChecked; + if (button != null) { + button.setChecked(isChecked); + } + } + + @Override + public int getInCallButtonId() { + return InCallButtonIds.BUTTON_AUDIO; + } + + @Override + public void setButton(CheckableLabeledButton button) { + this.button = button; + if (button != null) { + button.setEnabled(isEnabled && isAllowed); + button.setVisibility(View.VISIBLE); + button.setChecked(isChecked); + button.setOnClickListener(checkable ? null : this); + button.setOnCheckedChangeListener(checkable ? this : null); + button.setLabelText(label); + button.setIconDrawable(icon); + button.setContentDescription( + isChecked ? checkedContentDescription : uncheckedContentDescription); + button.setShouldShowMoreIndicator(!checkable); + } + } + + public void setAudioState(CallAudioState audioState) { + @StringRes int contentDescriptionResId; + if ((audioState.getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH) + == CallAudioState.ROUTE_BLUETOOTH) { + checkable = false; + isChecked = false; + label = R.string.incall_label_audio; + + if ((audioState.getRoute() & CallAudioState.ROUTE_BLUETOOTH) + == CallAudioState.ROUTE_BLUETOOTH) { + icon = R.drawable.quantum_ic_bluetooth_audio_white_36; + contentDescriptionResId = R.string.incall_content_description_bluetooth; + } else if ((audioState.getRoute() & CallAudioState.ROUTE_SPEAKER) + == CallAudioState.ROUTE_SPEAKER) { + icon = R.drawable.quantum_ic_volume_up_white_36; + contentDescriptionResId = R.string.incall_content_description_speaker; + } else if ((audioState.getRoute() & CallAudioState.ROUTE_WIRED_HEADSET) + == CallAudioState.ROUTE_WIRED_HEADSET) { + icon = R.drawable.quantum_ic_headset_white_36; + contentDescriptionResId = R.string.incall_content_description_headset; + } else { + icon = R.drawable.ic_phone_audio_white_36dp; + contentDescriptionResId = R.string.incall_content_description_earpiece; + } + } else { + checkable = true; + isChecked = audioState.getRoute() == CallAudioState.ROUTE_SPEAKER; + label = R.string.incall_label_speaker; + icon = R.drawable.quantum_ic_volume_up_white_36; + contentDescriptionResId = R.string.incall_content_description_speaker; + } + + contentDescription = delegate.getContext().getText(contentDescriptionResId); + checkedContentDescription = + TextUtils.concat( + contentDescription, + delegate.getContext().getText(R.string.incall_talkback_speaker_on)); + uncheckedContentDescription = + TextUtils.concat( + contentDescription, + delegate.getContext().getText(R.string.incall_talkback_speaker_off)); + setButton(button); + } + + @Override + public void onClick(View v) { + delegate.showAudioRouteSelector(); + } + + @Override + public void onCheckedChanged(CheckableLabeledButton checkableLabeledButton, boolean isChecked) { + checkableLabeledButton.setContentDescription( + isChecked ? checkedContentDescription : uncheckedContentDescription); + delegate.toggleSpeakerphone(); + } + } + + class DialpadButtonController extends SimpleCheckableButtonController { + + public DialpadButtonController(@NonNull InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_DIALPAD, + 0, + 0, + R.string.incall_label_dialpad, + R.drawable.quantum_ic_dialpad_white_36); + } + + @Override + public void doCheckedChanged(boolean isChecked) { + delegate.showDialpadClicked(isChecked); + } + } + + class HoldButtonController extends SimpleCheckableButtonController { + + public HoldButtonController(@NonNull InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_HOLD, + R.string.incall_content_description_unhold, + R.string.incall_content_description_hold, + R.string.incall_label_hold, + R.drawable.quantum_ic_pause_white_36); + } + + @Override + public void doCheckedChanged(boolean isChecked) { + delegate.holdClicked(isChecked); + } + } + + class AddCallButtonController extends SimpleNonCheckableButtonController { + + public AddCallButtonController(@NonNull InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_ADD_CALL, + 0, + R.string.incall_label_add_call, + R.drawable.ic_addcall_white); + Assert.isNotNull(delegate); + } + + @Override + public void onClick(View view) { + delegate.addCallClicked(); + } + } + + class SwapButtonController extends SimpleNonCheckableButtonController { + + public SwapButtonController(@NonNull InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_SWAP, + R.string.incall_content_description_swap_calls, + R.string.incall_label_swap, + R.drawable.quantum_ic_swap_calls_white_36); + Assert.isNotNull(delegate); + } + + @Override + public void onClick(View view) { + delegate.swapClicked(); + } + } + + class MergeButtonController extends SimpleNonCheckableButtonController { + + public MergeButtonController(@NonNull InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_MERGE, + R.string.incall_content_description_merge_calls, + R.string.incall_label_merge, + R.drawable.quantum_ic_call_merge_white_36); + Assert.isNotNull(delegate); + } + + @Override + public void onClick(View view) { + delegate.mergeClicked(); + } + } + + class UpgradeToVideoButtonController extends SimpleNonCheckableButtonController { + + public UpgradeToVideoButtonController(@NonNull InCallButtonUiDelegate delegate) { + super( + delegate, + InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO, + 0, + R.string.incall_label_videocall, + R.drawable.quantum_ic_videocam_white_36); + Assert.isNotNull(delegate); + } + + @Override + public void onClick(View view) { + delegate.changeToVideoClicked(); + } + } + + class ManageConferenceButtonController extends SimpleNonCheckableButtonController { + + private final InCallScreenDelegate inCallScreenDelegate; + + public ManageConferenceButtonController(@NonNull InCallScreenDelegate inCallScreenDelegate) { + super( + null, + InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE, + R.string.a11y_description_incall_label_manage_content, + R.string.incall_label_manage, + R.drawable.quantum_ic_group_white_36); + Assert.isNotNull(inCallScreenDelegate); + this.inCallScreenDelegate = inCallScreenDelegate; + } + + @Override + public void onClick(View view) { + inCallScreenDelegate.onManageConferenceClicked(); + } + } + + class SwitchToSecondaryButtonController extends SimpleNonCheckableButtonController { + + private final InCallScreenDelegate inCallScreenDelegate; + + public SwitchToSecondaryButtonController(InCallScreenDelegate inCallScreenDelegate) { + super( + null, + InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY, + R.string.incall_content_description_swap_calls, + R.string.incall_label_swap, + R.drawable.quantum_ic_swap_calls_white_36); + Assert.isNotNull(inCallScreenDelegate); + this.inCallScreenDelegate = inCallScreenDelegate; + } + + @Override + public void onClick(View view) { + inCallScreenDelegate.onSecondaryInfoClicked(); + } + } +} |