summaryrefslogtreecommitdiff
path: root/java/com/android/incallui/InCallActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/incallui/InCallActivity.java')
-rw-r--r--java/com/android/incallui/InCallActivity.java756
1 files changed, 756 insertions, 0 deletions
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
new file mode 100644
index 000000000..307415916
--- /dev/null
+++ b/java/com/android/incallui/InCallActivity.java
@@ -0,0 +1,756 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.GradientDrawable.Orientation;
+import android.os.Bundle;
+import android.support.annotation.ColorInt;
+import android.support.annotation.FloatRange;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.graphics.ColorUtils;
+import android.telecom.DisconnectCause;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.compat.ActivityCompat;
+import com.android.dialer.logging.Logger;
+import com.android.dialer.logging.nano.ScreenEvent;
+import com.android.incallui.answer.bindings.AnswerBindings;
+import com.android.incallui.answer.protocol.AnswerScreen;
+import com.android.incallui.answer.protocol.AnswerScreenDelegate;
+import com.android.incallui.answer.protocol.AnswerScreenDelegateFactory;
+import com.android.incallui.answerproximitysensor.PseudoScreenState;
+import com.android.incallui.call.CallList;
+import com.android.incallui.call.DialerCall;
+import com.android.incallui.call.DialerCall.State;
+import com.android.incallui.call.VideoUtils;
+import com.android.incallui.incall.bindings.InCallBindings;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
+import com.android.incallui.incall.protocol.InCallScreen;
+import com.android.incallui.incall.protocol.InCallScreenDelegate;
+import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
+import com.android.incallui.video.bindings.VideoBindings;
+import com.android.incallui.video.protocol.VideoCallScreen;
+import com.android.incallui.video.protocol.VideoCallScreenDelegate;
+import com.android.incallui.video.protocol.VideoCallScreenDelegateFactory;
+
+/** Version of {@link InCallActivity} that shows the new UI */
+public class InCallActivity extends TransactionSafeFragmentActivity
+ implements AnswerScreenDelegateFactory,
+ InCallScreenDelegateFactory,
+ InCallButtonUiDelegateFactory,
+ VideoCallScreenDelegateFactory,
+ PseudoScreenState.StateChangedListener {
+
+ private static final String TAG_IN_CALL_SCREEN = "tag_in_call_screen";
+ private static final String TAG_ANSWER_SCREEN = "tag_answer_screen";
+ private static final String TAG_VIDEO_CALL_SCREEN = "tag_video_call_screen";
+
+ private static final String DID_SHOW_ANSWER_SCREEN_KEY = "did_show_answer_screen";
+ private static final String DID_SHOW_IN_CALL_SCREEN_KEY = "did_show_in_call_screen";
+ private static final String DID_SHOW_VIDEO_CALL_SCREEN_KEY = "did_show_video_call_screen";
+
+ private final InCallActivityCommon common;
+ private boolean didShowAnswerScreen;
+ private boolean didShowInCallScreen;
+ private boolean didShowVideoCallScreen;
+ private int[] backgroundDrawableColors;
+ private GradientDrawable backgroundDrawable;
+ private boolean isVisible;
+ private View pseudoBlackScreenOverlay;
+ private boolean touchDownWhenPseudoScreenOff;
+ private boolean isInShowMainInCallFragment;
+ private boolean needDismissPendingDialogs;
+
+ public InCallActivity() {
+ common = new InCallActivityCommon(this);
+ }
+
+ public static Intent getIntent(
+ Context context,
+ boolean showDialpad,
+ boolean newOutgoingCall,
+ boolean isVideoCall,
+ boolean isForFullScreen) {
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClass(context, InCallActivity.class);
+ InCallActivityCommon.setIntentExtras(intent, showDialpad, newOutgoingCall, isForFullScreen);
+ return intent;
+ }
+
+ @Override
+ protected void onResumeFragments() {
+ super.onResumeFragments();
+ if (needDismissPendingDialogs) {
+ dismissPendingDialogs();
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ LogUtil.i("InCallActivity.onCreate", "");
+ super.onCreate(icicle);
+
+ if (icicle != null) {
+ didShowAnswerScreen = icicle.getBoolean(DID_SHOW_ANSWER_SCREEN_KEY);
+ didShowInCallScreen = icicle.getBoolean(DID_SHOW_IN_CALL_SCREEN_KEY);
+ didShowVideoCallScreen = icicle.getBoolean(DID_SHOW_VIDEO_CALL_SCREEN_KEY);
+ }
+
+ common.onCreate(icicle);
+
+ getWindow()
+ .getDecorView()
+ .setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+
+ pseudoBlackScreenOverlay = findViewById(R.id.psuedo_black_screen_overlay);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle out) {
+ LogUtil.i("InCallActivity.onSaveInstanceState", "");
+ common.onSaveInstanceState(out);
+ out.putBoolean(DID_SHOW_ANSWER_SCREEN_KEY, didShowAnswerScreen);
+ out.putBoolean(DID_SHOW_IN_CALL_SCREEN_KEY, didShowInCallScreen);
+ out.putBoolean(DID_SHOW_VIDEO_CALL_SCREEN_KEY, didShowVideoCallScreen);
+ super.onSaveInstanceState(out);
+ isVisible = false;
+ }
+
+ @Override
+ protected void onStart() {
+ LogUtil.i("InCallActivity.onStart", "");
+ super.onStart();
+ isVisible = true;
+ showMainInCallFragment();
+ common.onStart();
+ if (ActivityCompat.isInMultiWindowMode(this)
+ && !getResources().getBoolean(R.bool.incall_dialpad_allowed)) {
+ // Hide the dialpad because there may not be enough room
+ showDialpadFragment(false, false);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ LogUtil.i("InCallActivity.onResume", "");
+ super.onResume();
+ common.onResume();
+ PseudoScreenState pseudoScreenState = InCallPresenter.getInstance().getPseudoScreenState();
+ pseudoScreenState.addListener(this);
+ onPseudoScreenStateChanged(pseudoScreenState.isOn());
+ }
+
+ /** onPause is guaranteed to be called when the InCallActivity goes in the background. */
+ @Override
+ protected void onPause() {
+ LogUtil.i("InCallActivity.onPause", "");
+ super.onPause();
+ common.onPause();
+ InCallPresenter.getInstance().getPseudoScreenState().removeListener(this);
+ }
+
+ @Override
+ protected void onStop() {
+ LogUtil.i("InCallActivity.onStop", "");
+ super.onStop();
+ common.onStop();
+ isVisible = false;
+ }
+
+ @Override
+ protected void onDestroy() {
+ LogUtil.i("InCallActivity.onDestroy", "");
+ super.onDestroy();
+ common.onDestroy();
+ }
+
+ @Override
+ public void finish() {
+ if (shouldCloseActivityOnFinish()) {
+ super.finish();
+ }
+ }
+
+ private boolean shouldCloseActivityOnFinish() {
+ if (!isVisible()) {
+ LogUtil.i(
+ "InCallActivity.shouldCloseActivityOnFinish",
+ "allowing activity to be closed because it's not visible");
+ return true;
+ }
+
+ if (common.hasPendingDialogs()) {
+ LogUtil.i(
+ "InCallActivity.shouldCloseActivityOnFinish", "dialog is visible, not closing activity");
+ return false;
+ }
+
+ AnswerScreen answerScreen = getAnswerScreen();
+ if (answerScreen != null && answerScreen.hasPendingDialogs()) {
+ LogUtil.i(
+ "InCallActivity.shouldCloseActivityOnFinish",
+ "answer screen dialog is visible, not closing activity");
+ return false;
+ }
+
+ LogUtil.i(
+ "InCallActivity.shouldCloseActivityOnFinish",
+ "activity is visible and has no dialogs, allowing activity to close");
+ return true;
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ LogUtil.i("InCallActivity.onNewIntent", "");
+ common.onNewIntent(intent);
+
+ // If the screen is off, we need to make sure it gets turned on for incoming calls.
+ // This normally works just fine thanks to FLAG_TURN_SCREEN_ON but that only works
+ // when the activity is first created. Therefore, to ensure the screen is turned on
+ // for the call waiting case, we recreate() the current activity. There should be no jank from
+ // this since the screen is already off and will remain so until our new activity is up.
+ if (!isVisible()) {
+ LogUtil.i("InCallActivity.onNewIntent", "Restarting InCallActivity to force screen on.");
+ recreate();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ LogUtil.i("InCallActivity.onBackPressed", "");
+ if (!common.onBackPressed(didShowInCallScreen || didShowVideoCallScreen)) {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ LogUtil.i("InCallActivity.onOptionsItemSelected", "item: " + item);
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (common.onKeyUp(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (common.onKeyDown(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ public boolean isInCallScreenAnimating() {
+ return false;
+ }
+
+ public void showConferenceFragment(boolean show) {
+ if (show) {
+ startActivity(new Intent(this, ManageConferenceActivity.class));
+ }
+ }
+
+ public boolean showDialpadFragment(boolean show, boolean animate) {
+ boolean didChange = common.showDialpadFragment(show, animate);
+ if (didChange) {
+ // Note: onInCallScreenDialpadVisibilityChange is called here to ensure that the dialpad FAB
+ // repositions itself.
+ getInCallScreen().onInCallScreenDialpadVisibilityChange(show);
+ }
+ return didChange;
+ }
+
+ public boolean isDialpadVisible() {
+ return common.isDialpadVisible();
+ }
+
+ public void onForegroundCallChanged(DialerCall newForegroundCall) {
+ common.updateTaskDescription();
+ if (didShowAnswerScreen && newForegroundCall != null) {
+ if (newForegroundCall.getState() == State.DISCONNECTED
+ || newForegroundCall.getState() == State.IDLE) {
+ LogUtil.i(
+ "InCallActivity.onForegroundCallChanged",
+ "rejecting incoming call, not updating " + "window background color");
+ }
+ } else {
+ LogUtil.v("InCallActivity.onForegroundCallChanged", "resetting background color");
+ updateWindowBackgroundColor(0);
+ }
+ }
+
+ public void updateWindowBackgroundColor(@FloatRange(from = -1f, to = 1.0f) float progress) {
+ ThemeColorManager themeColorManager = InCallPresenter.getInstance().getThemeColorManager();
+ @ColorInt int top;
+ @ColorInt int middle;
+ @ColorInt int bottom;
+ @ColorInt int gray = 0x66000000;
+
+ if (ActivityCompat.isInMultiWindowMode(this)) {
+ top = themeColorManager.getBackgroundColorSolid();
+ middle = themeColorManager.getBackgroundColorSolid();
+ bottom = themeColorManager.getBackgroundColorSolid();
+ } else {
+ top = themeColorManager.getBackgroundColorTop();
+ middle = themeColorManager.getBackgroundColorMiddle();
+ bottom = themeColorManager.getBackgroundColorBottom();
+ }
+
+ if (progress < 0) {
+ float correctedProgress = Math.abs(progress);
+ top = ColorUtils.blendARGB(top, gray, correctedProgress);
+ middle = ColorUtils.blendARGB(middle, gray, correctedProgress);
+ bottom = ColorUtils.blendARGB(bottom, gray, correctedProgress);
+ }
+
+ boolean backgroundDirty = false;
+ if (backgroundDrawable == null) {
+ backgroundDrawableColors = new int[] {top, middle, bottom};
+ backgroundDrawable = new GradientDrawable(Orientation.TOP_BOTTOM, backgroundDrawableColors);
+ backgroundDirty = true;
+ } else {
+ if (backgroundDrawableColors[0] != top) {
+ backgroundDrawableColors[0] = top;
+ backgroundDirty = true;
+ }
+ if (backgroundDrawableColors[1] != middle) {
+ backgroundDrawableColors[1] = middle;
+ backgroundDirty = true;
+ }
+ if (backgroundDrawableColors[2] != bottom) {
+ backgroundDrawableColors[2] = bottom;
+ backgroundDirty = true;
+ }
+ if (backgroundDirty) {
+ backgroundDrawable.setColors(backgroundDrawableColors);
+ }
+ }
+
+ if (backgroundDirty) {
+ getWindow().setBackgroundDrawable(backgroundDrawable);
+ }
+ }
+
+ public boolean isVisible() {
+ return isVisible;
+ }
+
+ public boolean getCallCardFragmentVisible() {
+ return didShowInCallScreen || didShowVideoCallScreen;
+ }
+
+ public void dismissKeyguard(boolean dismiss) {
+ common.dismissKeyguard(dismiss);
+ }
+
+ public void showPostCharWaitDialog(String callId, String chars) {
+ common.showPostCharWaitDialog(callId, chars);
+ }
+
+ public void maybeShowErrorDialogOnDisconnect(DisconnectCause disconnectCause) {
+ common.maybeShowErrorDialogOnDisconnect(disconnectCause);
+ }
+
+ public void dismissPendingDialogs() {
+ if (isVisible) {
+ LogUtil.i("InCallActivity.dismissPendingDialogs", "");
+ common.dismissPendingDialogs();
+ AnswerScreen answerScreen = getAnswerScreen();
+ if (answerScreen != null) {
+ answerScreen.dismissPendingDialogs();
+ }
+ needDismissPendingDialogs = false;
+ } else {
+ // The activity is not visible and onSaveInstanceState may have been called so defer the
+ // dismissing action.
+ LogUtil.i(
+ "InCallActivity.dismissPendingDialogs", "defer actions since activity is not visible");
+ needDismissPendingDialogs = true;
+ }
+ }
+
+ private void enableInCallOrientationEventListener(boolean enable) {
+ common.enableInCallOrientationEventListener(enable);
+ }
+
+ public void setExcludeFromRecents(boolean exclude) {
+ common.setExcludeFromRecents(exclude);
+ }
+
+ public void onResolveIntent(
+ DialerCall outgoingCall, boolean isNewOutgoingCall, boolean didShowAccountSelectionDialog) {
+ if (didShowAccountSelectionDialog) {
+ hideMainInCallFragment();
+ }
+ }
+
+ @Nullable
+ public FragmentManager getDialpadFragmentManager() {
+ InCallScreen inCallScreen = getInCallScreen();
+ if (inCallScreen != null) {
+ return inCallScreen.getInCallScreenFragment().getChildFragmentManager();
+ }
+ return null;
+ }
+
+ public int getDialpadContainerId() {
+ return getInCallScreen().getAnswerAndDialpadContainerResourceId();
+ }
+
+ @Override
+ public AnswerScreenDelegate newAnswerScreenDelegate(AnswerScreen answerScreen) {
+ DialerCall call = CallList.getInstance().getCallById(answerScreen.getCallId());
+ if (call == null) {
+ // This is a work around for a bug where we attempt to create a new delegate after the call
+ // has already been removed. An example of when this can happen is:
+ // 1. incoming video call in landscape mode
+ // 2. remote party hangs up
+ // 3. activity switches from landscape to portrait
+ // At step #3 the answer fragment will try to create a new answer delegate but the call won't
+ // exist. In this case we'll simply return a stub delegate that does nothing. This is ok
+ // because this new state is transient and the activity will be destroyed soon.
+ LogUtil.i("InCallActivity.onPrimaryCallStateChanged", "call doesn't exist, using stub");
+ return new AnswerScreenPresenterStub();
+ } else {
+ return new AnswerScreenPresenter(
+ this, answerScreen, CallList.getInstance().getCallById(answerScreen.getCallId()));
+ }
+ }
+
+ @Override
+ public InCallScreenDelegate newInCallScreenDelegate() {
+ return new CallCardPresenter(this);
+ }
+
+ @Override
+ public InCallButtonUiDelegate newInCallButtonUiDelegate() {
+ return new CallButtonPresenter(this);
+ }
+
+ @Override
+ public VideoCallScreenDelegate newVideoCallScreenDelegate() {
+ return new VideoCallPresenter();
+ }
+
+ public void onPrimaryCallStateChanged() {
+ LogUtil.i("InCallActivity.onPrimaryCallStateChanged", "");
+ showMainInCallFragment();
+ }
+
+ public void onWiFiToLteHandover(DialerCall call) {
+ common.showWifiToLteHandoverToast(call);
+ }
+
+ public void onHandoverToWifiFailed(DialerCall call) {
+ common.showWifiFailedDialog(call);
+ }
+
+ public void setAllowOrientationChange(boolean allowOrientationChange) {
+ if (!allowOrientationChange) {
+ setRequestedOrientation(InCallOrientationEventListener.ACTIVITY_PREFERENCE_DISALLOW_ROTATION);
+ } else {
+ setRequestedOrientation(InCallOrientationEventListener.ACTIVITY_PREFERENCE_ALLOW_ROTATION);
+ }
+ enableInCallOrientationEventListener(allowOrientationChange);
+ }
+
+ private void hideMainInCallFragment() {
+ LogUtil.i("InCallActivity.hideMainInCallFragment", "");
+ if (didShowInCallScreen || didShowVideoCallScreen) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ hideInCallScreenFragment(transaction);
+ hideVideoCallScreenFragment(transaction);
+ transaction.commitAllowingStateLoss();
+ getSupportFragmentManager().executePendingTransactions();
+ }
+ }
+
+ private void showMainInCallFragment() {
+ // If the activity's onStart method hasn't been called yet then defer doing any work.
+ if (!isVisible) {
+ LogUtil.i("InCallActivity.showMainInCallFragment", "not visible yet/anymore");
+ return;
+ }
+
+ // Don't let this be reentrant.
+ if (isInShowMainInCallFragment) {
+ LogUtil.i("InCallActivity.showMainInCallFragment", "already in method, bailing");
+ return;
+ }
+
+ isInShowMainInCallFragment = true;
+ ShouldShowAnswerUiResult shouldShowAnswerUi = getShouldShowAnswerUi();
+ boolean shouldShowVideoUi = getShouldShowVideoUi();
+ LogUtil.i(
+ "InCallActivity.showMainInCallFragment",
+ "shouldShowAnswerUi: %b, shouldShowVideoUi: %b, "
+ + "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowVideoCallScreen: %b",
+ shouldShowAnswerUi.shouldShow,
+ shouldShowVideoUi,
+ didShowAnswerScreen,
+ didShowInCallScreen,
+ didShowVideoCallScreen);
+ // Only video call ui allows orientation change.
+ setAllowOrientationChange(shouldShowVideoUi);
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ boolean didChangeInCall;
+ boolean didChangeVideo;
+ boolean didChangeAnswer;
+ if (shouldShowAnswerUi.shouldShow) {
+ didChangeInCall = hideInCallScreenFragment(transaction);
+ didChangeVideo = hideVideoCallScreenFragment(transaction);
+ didChangeAnswer = showAnswerScreenFragment(transaction, shouldShowAnswerUi.call);
+ } else if (shouldShowVideoUi) {
+ didChangeInCall = hideInCallScreenFragment(transaction);
+ didChangeVideo = showVideoCallScreenFragment(transaction);
+ didChangeAnswer = hideAnswerScreenFragment(transaction);
+ } else {
+ didChangeInCall = showInCallScreenFragment(transaction);
+ didChangeVideo = hideVideoCallScreenFragment(transaction);
+ didChangeAnswer = hideAnswerScreenFragment(transaction);
+ }
+
+ if (didChangeInCall || didChangeVideo || didChangeAnswer) {
+ transaction.commitNow();
+ Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
+ }
+ isInShowMainInCallFragment = false;
+ }
+
+ private ShouldShowAnswerUiResult getShouldShowAnswerUi() {
+ DialerCall call = CallList.getInstance().getIncomingCall();
+ if (call != null) {
+ LogUtil.i("InCallActivity.getShouldShowAnswerUi", "found incoming call");
+ return new ShouldShowAnswerUiResult(true, call);
+ }
+
+ call = CallList.getInstance().getVideoUpgradeRequestCall();
+ if (call != null) {
+ LogUtil.i("InCallActivity.getShouldShowAnswerUi", "found video upgrade request");
+ return new ShouldShowAnswerUiResult(true, call);
+ }
+
+ // Check if we're showing the answer screen and the call is disconnected. If this condition is
+ // true then we won't switch from the answer UI to the in call UI. This prevents flicker when
+ // the user rejects an incoming call.
+ call = CallList.getInstance().getFirstCall();
+ if (call == null) {
+ call = CallList.getInstance().getBackgroundCall();
+ }
+ if (didShowAnswerScreen && (call == null || call.getState() == State.DISCONNECTED)) {
+ LogUtil.i("InCallActivity.getShouldShowAnswerUi", "found disconnecting incoming call");
+ return new ShouldShowAnswerUiResult(true, call);
+ }
+
+ return new ShouldShowAnswerUiResult(false, null);
+ }
+
+ private boolean getShouldShowVideoUi() {
+ DialerCall call = CallList.getInstance().getFirstCall();
+ if (call == null) {
+ LogUtil.i("InCallActivity.getShouldShowVideoUi", "null call");
+ return false;
+ }
+
+ if (VideoUtils.isVideoCall(call)) {
+ LogUtil.i("InCallActivity.getShouldShowVideoUi", "found video call");
+ return true;
+ }
+
+ if (VideoUtils.hasSentVideoUpgradeRequest(call)) {
+ LogUtil.i("InCallActivity.getShouldShowVideoUi", "upgrading to video");
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean showAnswerScreenFragment(FragmentTransaction transaction, DialerCall call) {
+ // When rejecting a call the active call can become null in which case we should continue
+ // showing the answer screen.
+ if (didShowAnswerScreen && call == null) {
+ return false;
+ }
+
+ boolean isVideoUpgradeRequest = VideoUtils.hasReceivedVideoUpgradeRequest(call);
+ int videoState = isVideoUpgradeRequest ? call.getRequestedVideoState() : call.getVideoState();
+
+ // Check if we're already showing an answer screen for this call.
+ if (didShowAnswerScreen) {
+ AnswerScreen answerScreen = getAnswerScreen();
+ if (answerScreen.getCallId().equals(call.getId())
+ && answerScreen.getVideoState() == videoState
+ && answerScreen.isVideoUpgradeRequest() == isVideoUpgradeRequest) {
+ return false;
+ }
+ LogUtil.i(
+ "InCallActivity.showAnswerScreenFragment",
+ "answer fragment exists but arguments do not match");
+ hideAnswerScreenFragment(transaction);
+ }
+
+ // Show a new answer screen.
+ AnswerScreen answerScreen =
+ AnswerBindings.createAnswerScreen(call.getId(), videoState, isVideoUpgradeRequest);
+ transaction.add(R.id.main, answerScreen.getAnswerScreenFragment(), TAG_ANSWER_SCREEN);
+
+ Logger.get(this).logScreenView(ScreenEvent.Type.INCOMING_CALL, this);
+ didShowAnswerScreen = true;
+ return true;
+ }
+
+ private boolean hideAnswerScreenFragment(FragmentTransaction transaction) {
+ if (!didShowAnswerScreen) {
+ return false;
+ }
+ AnswerScreen answerScreen = getAnswerScreen();
+ if (answerScreen != null) {
+ transaction.remove(answerScreen.getAnswerScreenFragment());
+ }
+
+ didShowAnswerScreen = false;
+ return true;
+ }
+
+ private boolean showInCallScreenFragment(FragmentTransaction transaction) {
+ if (didShowInCallScreen) {
+ return false;
+ }
+ InCallScreen inCallScreen = getInCallScreen();
+ if (inCallScreen == null) {
+ inCallScreen = InCallBindings.createInCallScreen();
+ transaction.add(R.id.main, inCallScreen.getInCallScreenFragment(), TAG_IN_CALL_SCREEN);
+ } else {
+ transaction.show(inCallScreen.getInCallScreenFragment());
+ }
+ Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
+ didShowInCallScreen = true;
+ return true;
+ }
+
+ private boolean hideInCallScreenFragment(FragmentTransaction transaction) {
+ if (!didShowInCallScreen) {
+ return false;
+ }
+ InCallScreen inCallScreen = getInCallScreen();
+ if (inCallScreen != null) {
+ transaction.hide(inCallScreen.getInCallScreenFragment());
+ }
+ didShowInCallScreen = false;
+ return true;
+ }
+
+ private boolean showVideoCallScreenFragment(FragmentTransaction transaction) {
+ if (didShowVideoCallScreen) {
+ return false;
+ }
+
+ VideoCallScreen videoCallScreen = VideoBindings.createVideoCallScreen();
+ transaction.add(R.id.main, videoCallScreen.getVideoCallScreenFragment(), TAG_VIDEO_CALL_SCREEN);
+
+ Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
+ didShowVideoCallScreen = true;
+ return true;
+ }
+
+ private boolean hideVideoCallScreenFragment(FragmentTransaction transaction) {
+ if (!didShowVideoCallScreen) {
+ return false;
+ }
+ VideoCallScreen videoCallScreen = getVideoCallScreen();
+ if (videoCallScreen != null) {
+ transaction.remove(videoCallScreen.getVideoCallScreenFragment());
+ }
+ didShowVideoCallScreen = false;
+ return true;
+ }
+
+ AnswerScreen getAnswerScreen() {
+ return (AnswerScreen) getSupportFragmentManager().findFragmentByTag(TAG_ANSWER_SCREEN);
+ }
+
+ InCallScreen getInCallScreen() {
+ return (InCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_IN_CALL_SCREEN);
+ }
+
+ VideoCallScreen getVideoCallScreen() {
+ return (VideoCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_VIDEO_CALL_SCREEN);
+ }
+
+ @Override
+ public void onPseudoScreenStateChanged(boolean isOn) {
+ LogUtil.i("InCallActivity.onPseudoScreenStateChanged", "isOn: " + isOn);
+ pseudoBlackScreenOverlay.setVisibility(isOn ? View.GONE : View.VISIBLE);
+ }
+
+ /**
+ * For some touch related issue, turning off the screen can be faked by drawing a black view over
+ * the activity. All touch events started when the screen is "off" is rejected.
+ *
+ * @see PseudoScreenState
+ */
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ // Reject any gesture that started when the screen is in the fake off state.
+ if (touchDownWhenPseudoScreenOff) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ touchDownWhenPseudoScreenOff = false;
+ }
+ return true;
+ }
+ // Reject all touch event when the screen is in the fake off state.
+ if (!InCallPresenter.getInstance().getPseudoScreenState().isOn()) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ touchDownWhenPseudoScreenOff = true;
+ LogUtil.i("InCallActivity.dispatchTouchEvent", "touchDownWhenPseudoScreenOff");
+ }
+ return true;
+ }
+ return super.dispatchTouchEvent(event);
+ }
+
+ private static class ShouldShowAnswerUiResult {
+ public final boolean shouldShow;
+ public final DialerCall call;
+
+ ShouldShowAnswerUiResult(boolean shouldShow, DialerCall call) {
+ this.shouldShow = shouldShow;
+ this.call = call;
+ }
+ }
+}