blob: cc9a8e4385427d0ad3e3894aa8dfa597f46d4f3b [file] [log] [blame]
/*
* 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.NonNull;
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.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import com.android.dialer.common.Assert;
import com.android.dialer.common.ConfigProviderBindings;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.ActivityCompat;
import com.android.dialer.logging.Logger;
import com.android.dialer.logging.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.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 static final String CONFIG_ANSWER_AND_RELEASE_ENABLED = "answer_and_release_enabled";
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 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()) {
// When user select incall ui from recents after the call is disconnected, it tries to launch
// a new InCallActivity but InCallPresenter is already teared down at this point, which causes
// crash.
// By calling finishAndRemoveTask() instead of finish() the task associated with
// InCallActivity is cleared completely. So system won't try to create a new InCallActivity in
// this case.
//
// Calling finish won't clear the task and normally when an activity finishes it shouldn't
// clear the task since there could be parent activity in the same task that's still alive.
// But InCallActivity is special since it's singleInstance which means it's root activity and
// only instance of activity in the task. So it should be safe to also remove task when
// finishing.
// It's also necessary in the sense of it's excluded from recents. So whenever the activity
// finishes, the task should also be removed since it doesn't make sense to go back to it in
// anyway anymore.
super.finishAndRemoveTask();
}
}
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", "");
// 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()) {
common.onNewIntent(intent, true /* isRecreating */);
LogUtil.i("InCallActivity.onNewIntent", "Restarting InCallActivity to force screen on.");
recreate();
} else {
common.onNewIntent(intent, false /* isRecreating */);
}
}
@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) {
return common.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return common.onKeyDown(keyCode, event) || 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);
}
@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(VideoCallScreen videoCallScreen) {
DialerCall dialerCall = CallList.getInstance().getCallById(videoCallScreen.getCallId());
if (dialerCall != null && dialerCall.getVideoTech().shouldUseSurfaceView()) {
return dialerCall.getVideoTech().createVideoCallScreenDelegate(this, videoCallScreen);
}
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 onInternationalCallOnWifi(@NonNull DialerCall call) {
LogUtil.enterBlock("InCallActivity.onInternationalCallOnWifi");
common.showInternationalCallOnWifiDialog(call);
}
public void setAllowOrientationChange(boolean allowOrientationChange) {
if (!allowOrientationChange) {
setRequestedOrientation(InCallOrientationEventListener.ACTIVITY_PREFERENCE_DISALLOW_ROTATION);
} else {
setRequestedOrientation(InCallOrientationEventListener.ACTIVITY_PREFERENCE_ALLOW_ROTATION);
}
enableInCallOrientationEventListener(allowOrientationChange);
}
public 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;
ShouldShowUiResult shouldShowAnswerUi = getShouldShowAnswerUi();
ShouldShowUiResult shouldShowVideoUi = getShouldShowVideoUi();
LogUtil.i(
"InCallActivity.showMainInCallFragment",
"shouldShowAnswerUi: %b, shouldShowVideoUi: %b, "
+ "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowVideoCallScreen: %b",
shouldShowAnswerUi.shouldShow,
shouldShowVideoUi.shouldShow,
didShowAnswerScreen,
didShowInCallScreen,
didShowVideoCallScreen);
// Only video call ui allows orientation change.
setAllowOrientationChange(shouldShowVideoUi.shouldShow);
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.shouldShow) {
didChangeInCall = hideInCallScreenFragment(transaction);
didChangeVideo = showVideoCallScreenFragment(transaction, shouldShowVideoUi.call);
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 ShouldShowUiResult getShouldShowAnswerUi() {
DialerCall call = CallList.getInstance().getIncomingCall();
if (call != null) {
LogUtil.i("InCallActivity.getShouldShowAnswerUi", "found incoming call");
return new ShouldShowUiResult(true, call);
}
call = CallList.getInstance().getVideoUpgradeRequestCall();
if (call != null) {
LogUtil.i("InCallActivity.getShouldShowAnswerUi", "found video upgrade request");
return new ShouldShowUiResult(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 ShouldShowUiResult(true, call);
}
return new ShouldShowUiResult(false, null);
}
private static ShouldShowUiResult getShouldShowVideoUi() {
DialerCall call = CallList.getInstance().getFirstCall();
if (call == null) {
LogUtil.i("InCallActivity.getShouldShowVideoUi", "null call");
return new ShouldShowUiResult(false, null);
}
if (call.isVideoCall()) {
LogUtil.i("InCallActivity.getShouldShowVideoUi", "found video call");
return new ShouldShowUiResult(true, call);
}
if (call.hasSentVideoUpgradeRequest()) {
LogUtil.i("InCallActivity.getShouldShowVideoUi", "upgrading to video");
return new ShouldShowUiResult(true, call);
}
return new ShouldShowUiResult(false, null);
}
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;
}
Assert.checkArgument(call != null, "didShowAnswerScreen was false but call was still null");
boolean isVideoUpgradeRequest = call.hasReceivedVideoUpgradeRequest();
// Check if we're already showing an answer screen for this call.
if (didShowAnswerScreen) {
AnswerScreen answerScreen = getAnswerScreen();
if (answerScreen.getCallId().equals(call.getId())
&& answerScreen.isVideoCall() == call.isVideoCall()
&& 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(),
call.isVideoCall(),
isVideoUpgradeRequest,
call.getVideoTech().isSelfManagedCamera(),
shouldAllowAnswerAndRelease(call),
CallList.getInstance().getBackgroundCall() != null);
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 shouldAllowAnswerAndRelease(DialerCall call) {
if (CallList.getInstance().getActiveCall() == null) {
LogUtil.i("InCallActivity.shouldAllowAnswerAndRelease", "no active call");
return false;
}
if (getSystemService(TelephonyManager.class).getPhoneType()
== TelephonyManager.PHONE_TYPE_CDMA) {
LogUtil.i("InCallActivity.shouldAllowAnswerAndRelease", "PHONE_TYPE_CDMA not supported");
return false;
}
if (call.isVideoCall() || call.hasReceivedVideoUpgradeRequest()) {
LogUtil.i("InCallActivity.shouldAllowAnswerAndRelease", "video call");
return false;
}
if (!ConfigProviderBindings.get(this).getBoolean(CONFIG_ANSWER_AND_RELEASE_ENABLED, true)) {
LogUtil.i("InCallActivity.shouldAllowAnswerAndRelease", "disabled by config");
return false;
}
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, DialerCall call) {
if (didShowVideoCallScreen) {
VideoCallScreen videoCallScreen = getVideoCallScreen();
if (videoCallScreen.getCallId().equals(call.getId())) {
return false;
}
LogUtil.i(
"InCallActivity.showVideoCallScreenFragment",
"video call fragment exists but arguments do not match");
hideVideoCallScreenFragment(transaction);
}
LogUtil.i("InCallActivity.showVideoCallScreenFragment", "call: %s", call);
VideoCallScreen videoCallScreen =
VideoBindings.createVideoCallScreen(
call.getId(), call.getVideoTech().shouldUseSurfaceView());
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 ShouldShowUiResult {
public final boolean shouldShow;
public final DialerCall call;
ShouldShowUiResult(boolean shouldShow, DialerCall call) {
this.shouldShow = shouldShow;
this.call = call;
}
}
}