From 938468da6f5c225ebb161a68bd949c9cf3261892 Mon Sep 17 00:00:00 2001 From: Eric Erfanian Date: Tue, 24 Oct 2017 14:05:52 -0700 Subject: Rename the new bubble package name from "bubble" to "newbubble". It fixes AOSP for package name conflict. Test: manual PiperOrigin-RevId: 173298696 Change-Id: Id10ebe0bcf029e61f65cf6580c7198abd8395081 --- .../incallui/NewReturnToCallController.java | 283 +++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 java/com/android/incallui/NewReturnToCallController.java (limited to 'java/com/android/incallui/NewReturnToCallController.java') diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java new file mode 100644 index 000000000..cd69ea1be --- /dev/null +++ b/java/com/android/incallui/NewReturnToCallController.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2017 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; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Icon; +import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; +import android.telecom.CallAudioState; +import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderBindings; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.dialer.telecom.TelecomUtil; +import com.android.incallui.InCallPresenter.InCallUiListener; +import com.android.incallui.audiomode.AudioModeProvider; +import com.android.incallui.audiomode.AudioModeProvider.AudioModeListener; +import com.android.incallui.call.CallList; +import com.android.incallui.call.CallList.Listener; +import com.android.incallui.call.DialerCall; +import com.android.incallui.speakerbuttonlogic.SpeakerButtonInfo; +import com.android.incallui.speakerbuttonlogic.SpeakerButtonInfo.IconSize; +import com.android.newbubble.NewBubble; +import com.android.newbubble.NewBubble.BubbleExpansionStateListener; +import com.android.newbubble.NewBubble.ExpansionState; +import com.android.newbubble.NewBubbleInfo; +import com.android.newbubble.NewBubbleInfo.Action; +import java.util.ArrayList; +import java.util.List; + +/** + * Listens for events relevant to the return-to-call bubble and updates the bubble's state as + * necessary + */ +public class NewReturnToCallController implements InCallUiListener, Listener, AudioModeListener { + + public static final String RETURN_TO_CALL_EXTRA_KEY = "RETURN_TO_CALL_BUBBLE"; + + private final Context context; + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + NewBubble bubble; + + private CallAudioState audioState; + + private final PendingIntent toggleSpeaker; + private final PendingIntent showSpeakerSelect; + private final PendingIntent toggleMute; + private final PendingIntent endCall; + private final PendingIntent fullScreen; + + public static boolean isEnabled(Context context) { + return ConfigProviderBindings.get(context).getBoolean("enable_return_to_call_bubble_v2", false); + } + + public NewReturnToCallController(Context context) { + this.context = context; + + toggleSpeaker = createActionIntent(ReturnToCallActionReceiver.ACTION_TOGGLE_SPEAKER); + showSpeakerSelect = + createActionIntent(ReturnToCallActionReceiver.ACTION_SHOW_AUDIO_ROUTE_SELECTOR); + toggleMute = createActionIntent(ReturnToCallActionReceiver.ACTION_TOGGLE_MUTE); + endCall = createActionIntent(ReturnToCallActionReceiver.ACTION_END_CALL); + + Intent activityIntent = InCallActivity.getIntent(context, false, false, false); + activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + activityIntent.putExtra(RETURN_TO_CALL_EXTRA_KEY, true); + fullScreen = + PendingIntent.getActivity( + context, InCallActivity.PENDING_INTENT_REQUEST_CODE_BUBBLE, activityIntent, 0); + + InCallPresenter.getInstance().addInCallUiListener(this); + CallList.getInstance().addListener(this); + AudioModeProvider.getInstance().addListener(this); + audioState = AudioModeProvider.getInstance().getAudioState(); + } + + public void tearDown() { + InCallPresenter.getInstance().removeInCallUiListener(this); + CallList.getInstance().removeListener(this); + AudioModeProvider.getInstance().removeListener(this); + } + + @Override + public void onUiShowing(boolean showing) { + if (showing) { + hide(); + } else { + if (TelecomUtil.isInManagedCall(context)) { + show(); + } + } + } + + private void hide() { + if (bubble != null) { + bubble.hide(); + } else { + LogUtil.i("ReturnToCallController.hide", "hide() called without calling show()"); + } + } + + private void hideAndReset() { + if (bubble != null) { + bubble.hideAndReset(); + } else { + LogUtil.i("ReturnToCallController.reset", "reset() called without calling show()"); + } + } + + private void show() { + if (bubble == null) { + bubble = startBubble(); + } else { + bubble.show(); + } + } + + @VisibleForTesting + public NewBubble startBubble() { + if (!NewBubble.canShowBubbles(context)) { + LogUtil.i("ReturnToCallController.startNewBubble", "can't show bubble, no permission"); + return null; + } + NewBubble returnToCallBubble = NewBubble.createBubble(context, generateBubbleInfo()); + returnToCallBubble.setBubbleExpansionStateListener( + new BubbleExpansionStateListener() { + @Override + public void onBubbleExpansionStateChanged( + @ExpansionState int expansionState, boolean isUserAction) { + if (!isUserAction) { + return; + } + + DialerCall call = CallList.getInstance().getActiveOrBackgroundCall(); + switch (expansionState) { + case ExpansionState.START_EXPANDING: + if (call != null) { + Logger.get(context) + .logCallImpression( + DialerImpression.Type.BUBBLE_PRIMARY_BUTTON_EXPAND, + call.getUniqueCallId(), + call.getTimeAddedMs()); + } else { + Logger.get(context) + .logImpression(DialerImpression.Type.BUBBLE_PRIMARY_BUTTON_EXPAND); + } + break; + case ExpansionState.START_COLLAPSING: + if (call != null) { + Logger.get(context) + .logCallImpression( + DialerImpression.Type.BUBBLE_COLLAPSE_BY_USER, + call.getUniqueCallId(), + call.getTimeAddedMs()); + } else { + Logger.get(context).logImpression(DialerImpression.Type.BUBBLE_COLLAPSE_BY_USER); + } + break; + default: + break; + } + } + }); + returnToCallBubble.show(); + return returnToCallBubble; + } + + @Override + public void onIncomingCall(DialerCall call) {} + + @Override + public void onUpgradeToVideo(DialerCall call) {} + + @Override + public void onSessionModificationStateChange(DialerCall call) {} + + @Override + public void onCallListChange(CallList callList) {} + + @Override + public void onDisconnect(DialerCall call) { + if (call.wasParentCall()) { + // It's disconnected after the last child call is disconnected, and we already did everything + // for the last child. + LogUtil.i( + "ReturnToCallController.onDisconnect", "being called for a parent call and do nothing"); + return; + } + if (bubble != null + && bubble.isVisible() + && (!TelecomUtil.isInManagedCall(context) + || CallList.getInstance().getActiveOrBackgroundCall() != null)) { + bubble.showText(context.getText(R.string.incall_call_ended)); + } + // For conference call, we should hideAndReset for the last disconnected child call while the + // parent call is still there. + if (!CallList.getInstance().hasNonParentActiveOrBackgroundCall()) { + hideAndReset(); + } + } + + @Override + public void onWiFiToLteHandover(DialerCall call) {} + + @Override + public void onHandoverToWifiFailed(DialerCall call) {} + + @Override + public void onInternationalCallOnWifi(@NonNull DialerCall call) {} + + @Override + public void onAudioStateChanged(CallAudioState audioState) { + this.audioState = audioState; + if (bubble != null) { + bubble.updateActions(generateActions()); + } + } + + private NewBubbleInfo generateBubbleInfo() { + return NewBubbleInfo.builder() + .setPrimaryColor(context.getResources().getColor(R.color.dialer_theme_color, null)) + .setPrimaryIcon(Icon.createWithResource(context, R.drawable.on_going_call)) + .setStartingYPosition( + context.getResources().getDimensionPixelOffset(R.dimen.return_to_call_initial_offset_y)) + .setActions(generateActions()) + .build(); + } + + @NonNull + private List generateActions() { + List actions = new ArrayList<>(); + SpeakerButtonInfo speakerButtonInfo = new SpeakerButtonInfo(audioState, IconSize.SIZE_24_DP); + + actions.add( + Action.builder() + .setIconDrawable(context.getDrawable(R.drawable.quantum_ic_fullscreen_vd_theme_24)) + .setIntent(fullScreen) + .build()); + actions.add( + Action.builder() + .setIconDrawable(context.getDrawable(R.drawable.quantum_ic_mic_off_white_24)) + .setChecked(audioState.isMuted()) + .setIntent(toggleMute) + .build()); + actions.add( + Action.builder() + .setIconDrawable(context.getDrawable(speakerButtonInfo.icon)) + .setName(context.getText(speakerButtonInfo.label)) + .setChecked(speakerButtonInfo.isChecked) + .setIntent(speakerButtonInfo.checkable ? toggleSpeaker : showSpeakerSelect) + .build()); + actions.add( + Action.builder() + .setIconDrawable(context.getDrawable(R.drawable.quantum_ic_call_end_vd_theme_24)) + .setIntent(endCall) + .build()); + return actions; + } + + @NonNull + private PendingIntent createActionIntent(String action) { + Intent toggleSpeaker = new Intent(context, ReturnToCallActionReceiver.class); + toggleSpeaker.setAction(action); + return PendingIntent.getBroadcast(context, 0, toggleSpeaker, 0); + } +} -- cgit v1.2.3