diff options
Diffstat (limited to 'java/com/android/incallui/InCallActivity.java')
-rw-r--r-- | java/com/android/incallui/InCallActivity.java | 756 |
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; + } + } +} |