/** Brings the app into the foreground if possible. */ public void bringToForeground(boolean showDialpad) { // Before we bring the incall UI to the foreground, we check to see if: // 1. We've already started the activity once for this session // 2. If it exists, the activity is not already in the foreground // 3. We are in a state where we want to show the incall ui if (mIsActivityPreviouslyStarted && !isShowingInCallUi() && mInCallState != InCallState.NO_CALLS) { showInCall(showDialpad); } }
/** * When the state of in-call changes, this is the first method to get called. It determines if the * UI needs to be started or finished depending on the new state and does it. */ private InCallState startOrFinishUi(InCallState newState) { Log.d(this, "startOrFinishUi: " + mInCallState + " -> " + newState); // TODO: Consider a proper state machine implementation // If the state isn't changing, we have already done any starting/stopping of // activities in a previous pass...so lets cut out early if (newState == mInCallState) { return newState; } // A new Incoming call means that the user needs to be notified of the the call (since // it wasn't them who initiated it). We do this through full screen notifications and // happens indirectly through {@link StatusBarListener}. // // The process for incoming calls is as follows: // // 1) CallList - Announces existence of new INCOMING call // 2) InCallPresenter - Gets announcement and calculates that the new InCallState // - should be set to INCOMING. // 3) InCallPresenter - This method is called to see if we need to start or finish // the app given the new state. // 4) StatusBarNotifier - Listens to InCallState changes. InCallPresenter calls // StatusBarNotifier explicitly to issue a FullScreen Notification // that will either start the InCallActivity or show the user a // top-level notification dialog if the user is in an immersive app. // That notification can also start the InCallActivity. // 5) InCallActivity - Main activity starts up and at the end of its onCreate will // call InCallPresenter::setActivity() to let the presenter // know that start-up is complete. // // [ AND NOW YOU'RE IN THE CALL. voila! ] // // Our app is started using a fullScreen notification. We need to do this whenever // we get an incoming call. final boolean startStartupSequence = (InCallState.INCOMING == newState); // A new outgoing call indicates that the user just now dialed a number and when that // happens we need to display the screen immediateley. // // This is different from the incoming call sequence because we do not need to shock the // user with a top-level notification. Just show the call UI normally. final boolean showCallUi = (InCallState.OUTGOING == newState); // TODO: Can we be suddenly in a call without it having been in the outgoing or incoming // state? I havent seen that but if it can happen, the code below should be enabled. // showCallUi |= (InCallState.INCALL && !isActivityStarted()); // The only time that we have an instance of mInCallActivity and it isn't started is // when it is being destroyed. In that case, lets avoid bringing up another instance of // the activity. When it is finally destroyed, we double check if we should bring it back // up so we aren't going to lose anything by avoiding a second startup here. boolean activityIsFinishing = mInCallActivity != null && !isActivityStarted(); if (activityIsFinishing) { Log.i(this, "Undo the state change: " + newState + " -> " + mInCallState); return mInCallState; } if (showCallUi) { Log.i(this, "Start in call UI"); showInCall(false); } else if (startStartupSequence) { Log.i(this, "Start Full Screen in call UI"); // We're about the bring up the in-call UI for an incoming call. If we still have // dialogs up, we need to clear them out before showing incoming screen. if (isActivityStarted()) { mInCallActivity.dismissPendingDialogs(); } startUi(newState); } else if (newState == InCallState.NO_CALLS) { // The new state is the no calls state. Tear everything down. attemptFinishActivity(); attemptCleanup(); } return newState; }