summaryrefslogtreecommitdiff
path: root/InCallUI/src/com/android/incallui/InCallActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'InCallUI/src/com/android/incallui/InCallActivity.java')
-rw-r--r--InCallUI/src/com/android/incallui/InCallActivity.java980
1 files changed, 0 insertions, 980 deletions
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
deleted file mode 100644
index eaaedff2c..000000000
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * Copyright (C) 2006 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.ActionBar;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.AlertDialog;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Point;
-import android.hardware.SensorManager;
-import android.os.Bundle;
-import android.os.Trace;
-import android.telecom.DisconnectCause;
-import android.telecom.PhoneAccountHandle;
-import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.OrientationEventListener;
-import android.view.Surface;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-
-import com.android.contacts.common.activity.TransactionSafeActivity;
-import com.android.contacts.common.compat.CompatUtils;
-import com.android.contacts.common.interactions.TouchPointManager;
-import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
-import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment.SelectPhoneAccountListener;
-import com.android.dialer.R;
-import com.android.dialer.logging.Logger;
-import com.android.dialer.logging.ScreenEvent;
-import com.android.incallui.Call.State;
-import com.android.incallui.util.AccessibilityUtil;
-import com.android.phone.common.animation.AnimUtils;
-import com.android.phone.common.animation.AnimationListenerAdapter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Main activity that the user interacts with while in a live call.
- */
-public class InCallActivity extends TransactionSafeActivity implements FragmentDisplayManager {
-
- public static final String TAG = InCallActivity.class.getSimpleName();
-
- public static final String SHOW_DIALPAD_EXTRA = "InCallActivity.show_dialpad";
- public static final String DIALPAD_TEXT_EXTRA = "InCallActivity.dialpad_text";
- public static final String NEW_OUTGOING_CALL_EXTRA = "InCallActivity.new_outgoing_call";
- public static final String FOR_FULL_SCREEN_INTENT = "InCallActivity.for_full_screen_intent";
-
- private static final String TAG_DIALPAD_FRAGMENT = "tag_dialpad_fragment";
- private static final String TAG_CONFERENCE_FRAGMENT = "tag_conference_manager_fragment";
- private static final String TAG_CALLCARD_FRAGMENT = "tag_callcard_fragment";
- private static final String TAG_ANSWER_FRAGMENT = "tag_answer_fragment";
- private static final String TAG_SELECT_ACCT_FRAGMENT = "tag_select_acct_fragment";
-
- private static final int DIALPAD_REQUEST_NONE = 1;
- private static final int DIALPAD_REQUEST_SHOW = 2;
- private static final int DIALPAD_REQUEST_HIDE = 3;
-
- /**
- * This is used to relaunch the activity if resizing beyond which it needs to load different
- * layout file.
- */
- private static final int SCREEN_HEIGHT_RESIZE_THRESHOLD = 500;
-
- private CallButtonFragment mCallButtonFragment;
- private CallCardFragment mCallCardFragment;
- private AnswerFragment mAnswerFragment;
- private DialpadFragment mDialpadFragment;
- private ConferenceManagerFragment mConferenceManagerFragment;
- private FragmentManager mChildFragmentManager;
-
- private AlertDialog mDialog;
- private InCallOrientationEventListener mInCallOrientationEventListener;
-
- /**
- * Used to indicate whether the dialpad should be hidden or shown {@link #onResume}.
- * {@code #DIALPAD_REQUEST_SHOW} indicates that the dialpad should be shown.
- * {@code #DIALPAD_REQUEST_HIDE} indicates that the dialpad should be hidden.
- * {@code #DIALPAD_REQUEST_NONE} indicates no change should be made to dialpad visibility.
- */
- private int mShowDialpadRequest = DIALPAD_REQUEST_NONE;
-
- /**
- * Use to determine if the dialpad should be animated on show.
- */
- private boolean mAnimateDialpadOnShow;
-
- /**
- * Use to determine the DTMF Text which should be pre-populated in the dialpad.
- */
- private String mDtmfText;
-
- /**
- * Use to pass parameters for showing the PostCharDialog to {@link #onResume}
- */
- private boolean mShowPostCharWaitDialogOnResume;
- private String mShowPostCharWaitDialogCallId;
- private String mShowPostCharWaitDialogChars;
-
- private boolean mIsLandscape;
- private Animation mSlideIn;
- private Animation mSlideOut;
- private boolean mDismissKeyguard = false;
-
- AnimationListenerAdapter mSlideOutListener = new AnimationListenerAdapter() {
- @Override
- public void onAnimationEnd(Animation animation) {
- showFragment(TAG_DIALPAD_FRAGMENT, false, true);
- }
- };
-
- private OnTouchListener mDispatchTouchEventListener;
-
- private SelectPhoneAccountListener mSelectAcctListener = new SelectPhoneAccountListener() {
- @Override
- public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle,
- boolean setDefault) {
- InCallPresenter.getInstance().handleAccountSelection(selectedAccountHandle,
- setDefault);
- }
-
- @Override
- public void onDialogDismissed() {
- InCallPresenter.getInstance().cancelAccountSelection();
- }
- };
-
- @Override
- protected void onCreate(Bundle icicle) {
- Log.d(this, "onCreate()... this = " + this);
-
- super.onCreate(icicle);
-
- // set this flag so this activity will stay in front of the keyguard
- // Have the WindowManager filter out touch events that are "too fat".
- int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
-
- getWindow().addFlags(flags);
-
- // Setup action bar for the conference call manager.
- requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
- ActionBar actionBar = getActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowTitleEnabled(true);
- actionBar.hide();
- }
-
- // TODO(klp): Do we need to add this back when prox sensor is not available?
- // lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
-
- setContentView(R.layout.incall_screen);
-
- internalResolveIntent(getIntent());
-
- mIsLandscape = getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE;
-
- final boolean isRtl = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) ==
- View.LAYOUT_DIRECTION_RTL;
-
- if (mIsLandscape) {
- mSlideIn = AnimationUtils.loadAnimation(this,
- isRtl ? R.anim.dialpad_slide_in_left : R.anim.dialpad_slide_in_right);
- mSlideOut = AnimationUtils.loadAnimation(this,
- isRtl ? R.anim.dialpad_slide_out_left : R.anim.dialpad_slide_out_right);
- } else {
- mSlideIn = AnimationUtils.loadAnimation(this, R.anim.dialpad_slide_in_bottom);
- mSlideOut = AnimationUtils.loadAnimation(this, R.anim.dialpad_slide_out_bottom);
- }
-
- mSlideIn.setInterpolator(AnimUtils.EASE_IN);
- mSlideOut.setInterpolator(AnimUtils.EASE_OUT);
-
- mSlideOut.setAnimationListener(mSlideOutListener);
-
- // If the dialpad fragment already exists, retrieve it. This is important when rotating as
- // we will not be able to hide or show the dialpad after the rotation otherwise.
- Fragment existingFragment =
- getFragmentManager().findFragmentByTag(DialpadFragment.class.getName());
- if (existingFragment != null) {
- mDialpadFragment = (DialpadFragment) existingFragment;
- }
-
- if (icicle != null) {
- // If the dialpad was shown before, set variables indicating it should be shown and
- // populated with the previous DTMF text. The dialpad is actually shown and populated
- // in onResume() to ensure the hosting CallCardFragment has been inflated and is ready
- // to receive it.
- if (icicle.containsKey(SHOW_DIALPAD_EXTRA)) {
- boolean showDialpad = icicle.getBoolean(SHOW_DIALPAD_EXTRA);
- mShowDialpadRequest = showDialpad ? DIALPAD_REQUEST_SHOW : DIALPAD_REQUEST_HIDE;
- mAnimateDialpadOnShow = false;
- }
- mDtmfText = icicle.getString(DIALPAD_TEXT_EXTRA);
-
- SelectPhoneAccountDialogFragment dialogFragment = (SelectPhoneAccountDialogFragment)
- getFragmentManager().findFragmentByTag(TAG_SELECT_ACCT_FRAGMENT);
- if (dialogFragment != null) {
- dialogFragment.setListener(mSelectAcctListener);
- }
- }
- mInCallOrientationEventListener = new InCallOrientationEventListener(this);
-
- Log.d(this, "onCreate(): exit");
- }
-
- @Override
- protected void onSaveInstanceState(Bundle out) {
- // TODO: The dialpad fragment should handle this as part of its own state
- out.putBoolean(SHOW_DIALPAD_EXTRA,
- mCallButtonFragment != null && mCallButtonFragment.isDialpadVisible());
- if (mDialpadFragment != null) {
- out.putString(DIALPAD_TEXT_EXTRA, mDialpadFragment.getDtmfText());
- }
- super.onSaveInstanceState(out);
- }
-
- @Override
- protected void onStart() {
- Log.d(this, "onStart()...");
- super.onStart();
-
- // setting activity should be last thing in setup process
- InCallPresenter.getInstance().setActivity(this);
- enableInCallOrientationEventListener(getRequestedOrientation() ==
- InCallOrientationEventListener.FULL_SENSOR_SCREEN_ORIENTATION);
-
- InCallPresenter.getInstance().onActivityStarted();
- }
-
- @Override
- protected void onResume() {
- Log.i(this, "onResume()...");
- super.onResume();
-
- InCallPresenter.getInstance().setThemeColors();
- InCallPresenter.getInstance().onUiShowing(true);
-
- // Clear fullscreen state onResume; the stored value may not match reality.
- InCallPresenter.getInstance().clearFullscreen();
-
- // If there is a pending request to show or hide the dialpad, handle that now.
- if (mShowDialpadRequest != DIALPAD_REQUEST_NONE) {
- if (mShowDialpadRequest == DIALPAD_REQUEST_SHOW) {
- // Exit fullscreen so that the user has access to the dialpad hide/show button and
- // can hide the dialpad. Important when showing the dialpad from within dialer.
- InCallPresenter.getInstance().setFullScreen(false, true /* force */);
-
- mCallButtonFragment.displayDialpad(true /* show */,
- mAnimateDialpadOnShow /* animate */);
- mAnimateDialpadOnShow = false;
-
- if (mDialpadFragment != null) {
- mDialpadFragment.setDtmfText(mDtmfText);
- mDtmfText = null;
- }
- } else {
- Log.v(this, "onResume : force hide dialpad");
- if (mDialpadFragment != null) {
- mCallButtonFragment.displayDialpad(false /* show */, false /* animate */);
- }
- }
- mShowDialpadRequest = DIALPAD_REQUEST_NONE;
- }
-
- if (mShowPostCharWaitDialogOnResume) {
- showPostCharWaitDialog(mShowPostCharWaitDialogCallId, mShowPostCharWaitDialogChars);
- }
-
- CallList.getInstance().onInCallUiShown(
- getIntent().getBooleanExtra(FOR_FULL_SCREEN_INTENT, false));
- }
-
- // onPause is guaranteed to be called when the InCallActivity goes
- // in the background.
- @Override
- protected void onPause() {
- Log.d(this, "onPause()...");
- if (mDialpadFragment != null) {
- mDialpadFragment.onDialerKeyUp(null);
- }
-
- InCallPresenter.getInstance().onUiShowing(false);
- if (isFinishing()) {
- InCallPresenter.getInstance().unsetActivity(this);
- }
- super.onPause();
- }
-
- @Override
- protected void onStop() {
- Log.d(this, "onStop()...");
- enableInCallOrientationEventListener(false);
- InCallPresenter.getInstance().updateIsChangingConfigurations();
- InCallPresenter.getInstance().onActivityStopped();
- super.onStop();
- }
-
- @Override
- protected void onDestroy() {
- Log.d(this, "onDestroy()... this = " + this);
- InCallPresenter.getInstance().unsetActivity(this);
- InCallPresenter.getInstance().updateIsChangingConfigurations();
- super.onDestroy();
- }
-
- /**
- * When fragments have a parent fragment, onAttachFragment is not called on the parent
- * activity. To fix this, register our own callback instead that is always called for
- * all fragments.
- *
- * @see {@link BaseFragment#onAttach(Activity)}
- */
- @Override
- public void onFragmentAttached(Fragment fragment) {
- if (fragment instanceof DialpadFragment) {
- mDialpadFragment = (DialpadFragment) fragment;
- } else if (fragment instanceof AnswerFragment) {
- mAnswerFragment = (AnswerFragment) fragment;
- } else if (fragment instanceof CallCardFragment) {
- mCallCardFragment = (CallCardFragment) fragment;
- mChildFragmentManager = mCallCardFragment.getChildFragmentManager();
- } else if (fragment instanceof ConferenceManagerFragment) {
- mConferenceManagerFragment = (ConferenceManagerFragment) fragment;
- } else if (fragment instanceof CallButtonFragment) {
- mCallButtonFragment = (CallButtonFragment) fragment;
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- Configuration oldConfig = getResources().getConfiguration();
- Log.v(this, String.format(
- "incallui config changed, screen size: w%ddp x h%ddp old:w%ddp x h%ddp",
- newConfig.screenWidthDp, newConfig.screenHeightDp,
- oldConfig.screenWidthDp, oldConfig.screenHeightDp));
- // Recreate this activity if height is changing beyond the threshold to load different
- // layout file.
- if (oldConfig.screenHeightDp < SCREEN_HEIGHT_RESIZE_THRESHOLD &&
- newConfig.screenHeightDp > SCREEN_HEIGHT_RESIZE_THRESHOLD ||
- oldConfig.screenHeightDp > SCREEN_HEIGHT_RESIZE_THRESHOLD &&
- newConfig.screenHeightDp < SCREEN_HEIGHT_RESIZE_THRESHOLD) {
- Log.i(this, String.format(
- "Recreate activity due to resize beyond threshold: %d dp",
- SCREEN_HEIGHT_RESIZE_THRESHOLD));
- recreate();
- }
- }
-
- /**
- * Returns true when the Activity is currently visible.
- */
- /* package */ boolean isVisible() {
- return isSafeToCommitTransactions();
- }
-
- private boolean hasPendingDialogs() {
- return mDialog != null || (mAnswerFragment != null && mAnswerFragment.hasPendingDialogs());
- }
-
- @Override
- public void finish() {
- Log.i(this, "finish(). Dialog showing: " + (mDialog != null));
-
- // skip finish if we are still showing a dialog.
- if (!hasPendingDialogs()) {
- super.finish();
- }
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- Log.d(this, "onNewIntent: intent = " + intent);
-
- // We're being re-launched with a new Intent. Since it's possible for a
- // single InCallActivity instance to persist indefinitely (even if we
- // finish() ourselves), this sequence can potentially happen any time
- // the InCallActivity needs to be displayed.
-
- // Stash away the new intent so that we can get it in the future
- // by calling getIntent(). (Otherwise getIntent() will return the
- // original Intent from when we first got created!)
- setIntent(intent);
-
- // Activities are always paused before receiving a new intent, so
- // we can count on our onResume() method being called next.
-
- // Just like in onCreate(), handle the intent.
- internalResolveIntent(intent);
- }
-
- @Override
- public void onBackPressed() {
- Log.i(this, "onBackPressed");
-
- // BACK is also used to exit out of any "special modes" of the
- // in-call UI:
- if (!isVisible()) {
- return;
- }
-
- if ((mConferenceManagerFragment == null || !mConferenceManagerFragment.isVisible())
- && (mCallCardFragment == null || !mCallCardFragment.isVisible())) {
- return;
- }
-
- if (mDialpadFragment != null && mDialpadFragment.isVisible()) {
- mCallButtonFragment.displayDialpad(false /* show */, true /* animate */);
- return;
- } else if (mConferenceManagerFragment != null && mConferenceManagerFragment.isVisible()) {
- showConferenceFragment(false);
- return;
- }
-
- // Always disable the Back key while an incoming call is ringing
- final Call call = CallList.getInstance().getIncomingCall();
- if (call != null) {
- Log.i(this, "Consume Back press for an incoming call");
- return;
- }
-
- // Nothing special to do. Fall back to the default behavior.
- super.onBackPressed();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- final int itemId = item.getItemId();
- if (itemId == android.R.id.home) {
- onBackPressed();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- // push input to the dialer.
- if (mDialpadFragment != null && (mDialpadFragment.isVisible()) &&
- (mDialpadFragment.onDialerKeyUp(event))) {
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_CALL) {
- // Always consume CALL to be sure the PhoneWindow won't do anything with it
- return true;
- }
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (mDispatchTouchEventListener != null) {
- boolean handled = mDispatchTouchEventListener.onTouch(null, ev);
- if (handled) {
- return true;
- }
- }
- return super.dispatchTouchEvent(ev);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_CALL:
- boolean handled = InCallPresenter.getInstance().handleCallKey();
- if (!handled) {
- Log.w(this, "InCallActivity should always handle KEYCODE_CALL in onKeyDown");
- }
- // Always consume CALL to be sure the PhoneWindow won't do anything with it
- return true;
-
- // Note there's no KeyEvent.KEYCODE_ENDCALL case here.
- // The standard system-wide handling of the ENDCALL key
- // (see PhoneWindowManager's handling of KEYCODE_ENDCALL)
- // already implements exactly what the UI spec wants,
- // namely (1) "hang up" if there's a current active call,
- // or (2) "don't answer" if there's a current ringing call.
-
- case KeyEvent.KEYCODE_CAMERA:
- // Disable the CAMERA button while in-call since it's too
- // easy to press accidentally.
- return true;
-
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_MUTE:
- // Ringer silencing handled by PhoneWindowManager.
- break;
-
- case KeyEvent.KEYCODE_MUTE:
- // toggle mute
- TelecomAdapter.getInstance().mute(!AudioModeProvider.getInstance().getMute());
- return true;
-
- // Various testing/debugging features, enabled ONLY when VERBOSE == true.
- case KeyEvent.KEYCODE_SLASH:
- if (Log.VERBOSE) {
- Log.v(this, "----------- InCallActivity View dump --------------");
- // Dump starting from the top-level view of the entire activity:
- Window w = this.getWindow();
- View decorView = w.getDecorView();
- Log.d(this, "View dump:" + decorView);
- return true;
- }
- break;
- case KeyEvent.KEYCODE_EQUALS:
- // TODO: Dump phone state?
- break;
- }
-
- if (event.getRepeatCount() == 0 && handleDialerKeyDown(keyCode, event)) {
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- private boolean handleDialerKeyDown(int keyCode, KeyEvent event) {
- Log.v(this, "handleDialerKeyDown: keyCode " + keyCode + ", event " + event + "...");
-
- // As soon as the user starts typing valid dialable keys on the
- // keyboard (presumably to type DTMF tones) we start passing the
- // key events to the DTMFDialer's onDialerKeyDown.
- if (mDialpadFragment != null && mDialpadFragment.isVisible()) {
- return mDialpadFragment.onDialerKeyDown(event);
- }
-
- return false;
- }
-
- public CallButtonFragment getCallButtonFragment() {
- return mCallButtonFragment;
- }
-
- public CallCardFragment getCallCardFragment() {
- return mCallCardFragment;
- }
-
- public AnswerFragment getAnswerFragment() {
- return mAnswerFragment;
- }
-
- private void internalResolveIntent(Intent intent) {
- final String action = intent.getAction();
- if (action.equals(Intent.ACTION_MAIN)) {
- // This action is the normal way to bring up the in-call UI.
- //
- // But we do check here for one extra that can come along with the
- // ACTION_MAIN intent:
-
- if (intent.hasExtra(SHOW_DIALPAD_EXTRA)) {
- // SHOW_DIALPAD_EXTRA can be used here to specify whether the DTMF
- // dialpad should be initially visible. If the extra isn't
- // present at all, we just leave the dialpad in its previous state.
-
- final boolean showDialpad = intent.getBooleanExtra(SHOW_DIALPAD_EXTRA, false);
- Log.d(this, "- internalResolveIntent: SHOW_DIALPAD_EXTRA: " + showDialpad);
-
- relaunchedFromDialer(showDialpad);
- }
-
- boolean newOutgoingCall = false;
- if (intent.getBooleanExtra(NEW_OUTGOING_CALL_EXTRA, false)) {
- intent.removeExtra(NEW_OUTGOING_CALL_EXTRA);
- Call call = CallList.getInstance().getOutgoingCall();
- if (call == null) {
- call = CallList.getInstance().getPendingOutgoingCall();
- }
-
- Bundle extras = null;
- if (call != null) {
- extras = call.getTelecomCall().getDetails().getIntentExtras();
- }
- if (extras == null) {
- // Initialize the extras bundle to avoid NPE
- extras = new Bundle();
- }
-
- Point touchPoint = null;
- if (TouchPointManager.getInstance().hasValidPoint()) {
- // Use the most immediate touch point in the InCallUi if available
- touchPoint = TouchPointManager.getInstance().getPoint();
- } else {
- // Otherwise retrieve the touch point from the call intent
- if (call != null) {
- touchPoint = (Point) extras.getParcelable(TouchPointManager.TOUCH_POINT);
- }
- }
-
- // Start animation for new outgoing call
- CircularRevealFragment.startCircularReveal(getFragmentManager(), touchPoint,
- InCallPresenter.getInstance());
-
- // InCallActivity is responsible for disconnecting a new outgoing call if there
- // is no way of making it (i.e. no valid call capable accounts).
- // If the version is not MSIM compatible, then ignore this code.
- if (CompatUtils.isMSIMCompatible()
- && InCallPresenter.isCallWithNoValidAccounts(call)) {
- TelecomAdapter.getInstance().disconnectCall(call.getId());
- }
-
- dismissKeyguard(true);
- newOutgoingCall = true;
- }
-
- Call pendingAccountSelectionCall = CallList.getInstance().getWaitingForAccountCall();
- if (pendingAccountSelectionCall != null) {
- showCallCardFragment(false);
- Bundle extras =
- pendingAccountSelectionCall.getTelecomCall().getDetails().getIntentExtras();
-
- final List<PhoneAccountHandle> phoneAccountHandles;
- if (extras != null) {
- phoneAccountHandles = extras.getParcelableArrayList(
- android.telecom.Call.AVAILABLE_PHONE_ACCOUNTS);
- } else {
- phoneAccountHandles = new ArrayList<>();
- }
-
- DialogFragment dialogFragment = SelectPhoneAccountDialogFragment.newInstance(
- R.string.select_phone_account_for_calls, true, phoneAccountHandles,
- mSelectAcctListener);
- dialogFragment.show(getFragmentManager(), TAG_SELECT_ACCT_FRAGMENT);
- } else if (!newOutgoingCall) {
- showCallCardFragment(true);
- }
- return;
- }
- }
-
- /**
- * When relaunching from the dialer app, {@code showDialpad} indicates whether the dialpad
- * should be shown on launch.
- *
- * @param showDialpad {@code true} to indicate the dialpad should be shown on launch, and
- * {@code false} to indicate no change should be made to the
- * dialpad visibility.
- */
- private void relaunchedFromDialer(boolean showDialpad) {
- mShowDialpadRequest = showDialpad ? DIALPAD_REQUEST_SHOW : DIALPAD_REQUEST_NONE;
- mAnimateDialpadOnShow = true;
-
- if (mShowDialpadRequest == DIALPAD_REQUEST_SHOW) {
- // If there's only one line in use, AND it's on hold, then we're sure the user
- // wants to use the dialpad toward the exact line, so un-hold the holding line.
- final Call call = CallList.getInstance().getActiveOrBackgroundCall();
- if (call != null && call.getState() == State.ONHOLD) {
- TelecomAdapter.getInstance().unholdCall(call.getId());
- }
- }
- }
-
- public void dismissKeyguard(boolean dismiss) {
- if (mDismissKeyguard == dismiss) {
- return;
- }
- mDismissKeyguard = dismiss;
- if (dismiss) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- } else {
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- }
- }
-
- private void showFragment(String tag, boolean show, boolean executeImmediately) {
- Trace.beginSection("showFragment - " + tag);
- final FragmentManager fm = getFragmentManagerForTag(tag);
-
- if (fm == null) {
- Log.w(TAG, "Fragment manager is null for : " + tag);
- return;
- }
-
- Fragment fragment = fm.findFragmentByTag(tag);
- if (!show && fragment == null) {
- // Nothing to show, so bail early.
- return;
- }
-
- final FragmentTransaction transaction = fm.beginTransaction();
- if (show) {
- if (fragment == null) {
- fragment = createNewFragmentForTag(tag);
- transaction.add(getContainerIdForFragment(tag), fragment, tag);
- } else {
- transaction.show(fragment);
- }
- Logger.logScreenView(getScreenTypeForTag(tag), this);
- } else {
- transaction.hide(fragment);
- }
-
- transaction.commitAllowingStateLoss();
- if (executeImmediately) {
- fm.executePendingTransactions();
- }
- Trace.endSection();
- }
-
- private Fragment createNewFragmentForTag(String tag) {
- if (TAG_DIALPAD_FRAGMENT.equals(tag)) {
- mDialpadFragment = new DialpadFragment();
- return mDialpadFragment;
- } else if (TAG_ANSWER_FRAGMENT.equals(tag)) {
- if (AccessibilityUtil.isTalkBackEnabled(this)) {
- mAnswerFragment = new AccessibleAnswerFragment();
- } else {
- mAnswerFragment = new GlowPadAnswerFragment();
- }
- return mAnswerFragment;
- } else if (TAG_CONFERENCE_FRAGMENT.equals(tag)) {
- mConferenceManagerFragment = new ConferenceManagerFragment();
- return mConferenceManagerFragment;
- } else if (TAG_CALLCARD_FRAGMENT.equals(tag)) {
- mCallCardFragment = new CallCardFragment();
- return mCallCardFragment;
- }
- throw new IllegalStateException("Unexpected fragment: " + tag);
- }
-
- private FragmentManager getFragmentManagerForTag(String tag) {
- if (TAG_DIALPAD_FRAGMENT.equals(tag)) {
- return mChildFragmentManager;
- } else if (TAG_ANSWER_FRAGMENT.equals(tag)) {
- return mChildFragmentManager;
- } else if (TAG_CONFERENCE_FRAGMENT.equals(tag)) {
- return getFragmentManager();
- } else if (TAG_CALLCARD_FRAGMENT.equals(tag)) {
- return getFragmentManager();
- }
- throw new IllegalStateException("Unexpected fragment: " + tag);
- }
-
- private int getScreenTypeForTag(String tag) {
- switch (tag) {
- case TAG_DIALPAD_FRAGMENT:
- return ScreenEvent.INCALL_DIALPAD;
- case TAG_CALLCARD_FRAGMENT:
- return ScreenEvent.INCALL;
- case TAG_CONFERENCE_FRAGMENT:
- return ScreenEvent.CONFERENCE_MANAGEMENT;
- case TAG_ANSWER_FRAGMENT:
- return ScreenEvent.INCOMING_CALL;
- default:
- return ScreenEvent.UNKNOWN;
- }
- }
-
- private int getContainerIdForFragment(String tag) {
- if (TAG_DIALPAD_FRAGMENT.equals(tag)) {
- return R.id.answer_and_dialpad_container;
- } else if (TAG_ANSWER_FRAGMENT.equals(tag)) {
- return R.id.answer_and_dialpad_container;
- } else if (TAG_CONFERENCE_FRAGMENT.equals(tag)) {
- return R.id.main;
- } else if (TAG_CALLCARD_FRAGMENT.equals(tag)) {
- return R.id.main;
- }
- throw new IllegalStateException("Unexpected fragment: " + tag);
- }
-
- /**
- * @return {@code true} while the visibility of the dialpad has actually changed.
- */
- public boolean showDialpadFragment(boolean show, boolean animate) {
- // If the dialpad is already visible, don't animate in. If it's gone, don't animate out.
- if ((show && isDialpadVisible()) || (!show && !isDialpadVisible())) {
- return false;
- }
- // We don't do a FragmentTransaction on the hide case because it will be dealt with when
- // the listener is fired after an animation finishes.
- if (!animate) {
- showFragment(TAG_DIALPAD_FRAGMENT, show, true);
- } else {
- if (show) {
- showFragment(TAG_DIALPAD_FRAGMENT, true, true);
- mDialpadFragment.animateShowDialpad();
- }
- mDialpadFragment.getView().startAnimation(show ? mSlideIn : mSlideOut);
- }
- // Note: onDialpadVisibilityChange is called here to ensure that the dialpad FAB
- // repositions itself.
- mCallCardFragment.onDialpadVisibilityChange(show);
-
- final ProximitySensor sensor = InCallPresenter.getInstance().getProximitySensor();
- if (sensor != null) {
- sensor.onDialpadVisible(show);
- }
- return true;
- }
-
- public boolean isDialpadVisible() {
- return mDialpadFragment != null && mDialpadFragment.isVisible();
- }
-
- public void showCallCardFragment(boolean show) {
- showFragment(TAG_CALLCARD_FRAGMENT, show, true);
- }
-
- /**
- * Hides or shows the conference manager fragment.
- *
- * @param show {@code true} if the conference manager should be shown, {@code false} if it
- * should be hidden.
- */
- public void showConferenceFragment(boolean show) {
- showFragment(TAG_CONFERENCE_FRAGMENT, show, true);
- mConferenceManagerFragment.onVisibilityChanged(show);
-
- // Need to hide the call card fragment to ensure that accessibility service does not try to
- // give focus to the call card when the conference manager is visible.
- mCallCardFragment.getView().setVisibility(show ? View.GONE : View.VISIBLE);
- }
-
- public void showAnswerFragment(boolean show) {
- // CallCardFragment is the parent fragment of AnswerFragment.
- // Must create the CallCardFragment first before creating
- // AnswerFragment if CallCardFragment is null.
- if (show && getCallCardFragment() == null) {
- showCallCardFragment(true);
- }
- showFragment(TAG_ANSWER_FRAGMENT, show, true);
- }
-
- public void showPostCharWaitDialog(String callId, String chars) {
- if (isVisible()) {
- final PostCharDialogFragment fragment = new PostCharDialogFragment(callId, chars);
- fragment.show(getFragmentManager(), "postCharWait");
-
- mShowPostCharWaitDialogOnResume = false;
- mShowPostCharWaitDialogCallId = null;
- mShowPostCharWaitDialogChars = null;
- } else {
- mShowPostCharWaitDialogOnResume = true;
- mShowPostCharWaitDialogCallId = callId;
- mShowPostCharWaitDialogChars = chars;
- }
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- if (mCallCardFragment != null) {
- mCallCardFragment.dispatchPopulateAccessibilityEvent(event);
- }
- return super.dispatchPopulateAccessibilityEvent(event);
- }
-
- public void maybeShowErrorDialogOnDisconnect(DisconnectCause disconnectCause) {
- Log.d(this, "maybeShowErrorDialogOnDisconnect");
-
- if (!isFinishing() && !TextUtils.isEmpty(disconnectCause.getDescription())
- && (disconnectCause.getCode() == DisconnectCause.ERROR ||
- disconnectCause.getCode() == DisconnectCause.RESTRICTED)) {
- showErrorDialog(disconnectCause.getDescription());
- }
- }
-
- public void dismissPendingDialogs() {
- if (mDialog != null) {
- mDialog.dismiss();
- mDialog = null;
- }
- if (mAnswerFragment != null) {
- mAnswerFragment.dismissPendingDialogs();
- }
-
- SelectPhoneAccountDialogFragment dialogFragment = (SelectPhoneAccountDialogFragment)
- getFragmentManager().findFragmentByTag(TAG_SELECT_ACCT_FRAGMENT);
- if (dialogFragment != null) {
- dialogFragment.dismiss();
- }
- }
-
- /**
- * Utility function to bring up a generic "error" dialog.
- */
- private void showErrorDialog(CharSequence msg) {
- Log.i(this, "Show Dialog: " + msg);
-
- dismissPendingDialogs();
-
- mDialog = new AlertDialog.Builder(this)
- .setMessage(msg)
- .setPositiveButton(android.R.string.ok, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- onDialogDismissed();
- }
- })
- .setOnCancelListener(new OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- onDialogDismissed();
- }
- })
- .create();
-
- mDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- mDialog.show();
- }
-
- private void onDialogDismissed() {
- mDialog = null;
- CallList.getInstance().onErrorDialogDismissed();
- InCallPresenter.getInstance().onDismissDialog();
- }
-
- public void setExcludeFromRecents(boolean exclude) {
- ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.AppTask> tasks = am.getAppTasks();
- int taskId = getTaskId();
- for (int i = 0; i < tasks.size(); i++) {
- ActivityManager.AppTask task = tasks.get(i);
- if (task.getTaskInfo().id == taskId) {
- try {
- task.setExcludeFromRecents(exclude);
- } catch (RuntimeException e) {
- Log.e(TAG, "RuntimeException when excluding task from recents.", e);
- }
- }
- }
- }
-
-
- public OnTouchListener getDispatchTouchEventListener() {
- return mDispatchTouchEventListener;
- }
-
- public void setDispatchTouchEventListener(OnTouchListener mDispatchTouchEventListener) {
- this.mDispatchTouchEventListener = mDispatchTouchEventListener;
- }
-
- /**
- * Enables the OrientationEventListener if enable flag is true. Disables it if enable is
- * false
- * @param enable true or false.
- */
- public void enableInCallOrientationEventListener(boolean enable) {
- if (enable) {
- mInCallOrientationEventListener.enable(enable);
- } else {
- mInCallOrientationEventListener.disable();
- }
- }
-}