summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSantos Cordon <santoscordon@google.com>2013-08-08 02:07:10 -0700
committerSantos Cordon <santoscordon@google.com>2013-08-08 18:59:25 +0000
commite067a78c4c0817e9e81c41327460aedce7f1091d (patch)
treec9253619fa841e89690979ec82009c8a6670514d
parentb6404417362ca02c940807426fefdb7568e269e3 (diff)
Improve outgoing call sequence
Changes: - When we get a new outgoing call, fire up the UI (without the notification) by sending it an ACTION_MAIN intent. - Fix up the InCallState-setting code in InCallPresenter to be a little cleaner and accomodate new OUTGOING code. - Add missing call to set HOLD Ui button - Fix an occassional NullPointerException in CallCardPresenter.java Change-Id: I557a777287d9ab25ef1447be63b5da080f1b2532 (cherry picked from commit 4d5c29af103c13e78568dc772d26eb56a3e6d3e1)
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonPresenter.java2
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java10
-rw-r--r--InCallUI/src/com/android/incallui/InCallActivity.java42
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java110
4 files changed, 143 insertions, 21 deletions
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index 7b6649704..a307009f9 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -182,6 +182,8 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
Logger.v(this, "Show swap ", call.can(Capabilities.SWAP_CALLS));
Logger.v(this, "Show add call ", call.can(Capabilities.ADD_CALL));
+ ui.setHold(call.getState() == Call.State.ONHOLD);
+
ui.showHold(call.can(Capabilities.HOLD));
ui.showMerge(call.can(Capabilities.MERGE_CALLS));
ui.showSwap(call.can(Capabilities.SWAP_CALLS));
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index d97c22e57..f709abed9 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -86,12 +86,14 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi> i
Logger.d(this, "Primary call: " + primary);
Logger.d(this, "Secondary call: " + secondary);
- // Set primary call data
- final CallerInfo primaryCallInfo = CallerInfoUtils.getCallerInfoForCall(mContext, primary,
- null, this);
- updateDisplayByCallerInfo(primary, primaryCallInfo, primary.getNumberPresentation(), true);
if (primary != null) {
+ // Set primary call data
+ final CallerInfo primaryCallInfo = CallerInfoUtils.getCallerInfoForCall(mContext,
+ primary, null, this);
+ updateDisplayByCallerInfo(primary, primaryCallInfo, primary.getNumberPresentation(),
+ true);
+
ui.setNumber(primary.getNumber());
ui.setCallState(primary.getState(), primary.getDisconnectCause());
} else {
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 28e02b3b3..8ff43d5a1 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -129,7 +129,7 @@ public class InCallActivity extends Activity {
// we can count on our onResume() method being called next.
// Just like in onCreate(), handle the intent.
- //TODO(klp): handle intent
+ internalResolveIntent(intent);
}
@Override
@@ -199,6 +199,46 @@ public class InCallActivity extends Activity {
return super.onKeyDown(keyCode, event);
}
+ 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:
+
+ // TODO(klp): Enable this for klp
+ /*
+ 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.
+
+ boolean showDialpad = intent.getBooleanExtra(SHOW_DIALPAD_EXTRA, false);
+ if (VDBG) log("- internalResolveIntent: SHOW_DIALPAD_EXTRA: " + showDialpad);
+
+ // If SHOW_DIALPAD_EXTRA is specified, that overrides whatever
+ // the previous state of inCallUiState.showDialpad was.
+ mApp.inCallUiState.showDialpad = showDialpad;
+
+ final boolean hasActiveCall = mCM.hasActiveFgCall();
+ final boolean hasHoldingCall = mCM.hasActiveBgCall();
+
+ // There's only one line in use, AND it's on hold, at which we're sure the user
+ // wants to use the dialpad toward the exact line, so un-hold the holding line.
+ if (showDialpad && !hasActiveCall && hasHoldingCall) {
+ PhoneUtils.switchHoldingAndActive(mCM.getFirstActiveBgCall());
+ }
+ }
+ */
+ // ...and in onResume() we'll update the onscreen dialpad state to
+ // match the InCallUiState.
+
+ return;
+ }
+ }
+
private void initializeInCall() {
// TODO(klp): Make sure that this doesn't need to move back to onResume() since they are
// statically added fragments.
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 63f0aa524..83d520c59 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -41,6 +41,7 @@ public class InCallPresenter implements CallList.Listener {
private final StatusBarNotifier mStatusBarNotifier;
private final Set<InCallStateListener> mListeners = Sets.newHashSet();
+ private final Context mContext;
private InCallState mInCallState = InCallState.HIDDEN;
private InCallActivity mInCallActivity;
@@ -76,6 +77,10 @@ public class InCallPresenter implements CallList.Listener {
@Override
public void onCallListChange(CallList callList) {
// fast fail if we are still starting up
+ // TODO(klp): If the Activity crashes unexpectedly during start-up, we may never
+ // get out of STARTING_UP state and thus never attempt to recreate the activity a
+ // subsequent time. Test to see if this is the case and add a timeout for
+ // STARTING_UP phase.
if (mInCallState == InCallState.STARTING_UP) {
Logger.d(this, "Already on STARTING_UP, ignoring until ready");
return;
@@ -133,35 +138,108 @@ public class InCallPresenter implements CallList.Listener {
// TODO(klp): Consider a proper state machine implementation
- // if we need to show something, we need to start the Ui...
- if (!newState.isHidden()) {
+ // 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;
+ }
- // When we attempt to go to any state from HIDDEN, it means that we need to create the
- // entire UI. However, the StatusBarNotifier is in charge of starting up the Ui because
- // it has special behavior in case we have to deal with an immersive foreground app.
- // We set the STARTING_UP state to let StatusBarNotifier know it needs to start the
- // the Ui.
- if (mInCallState.isHidden()) {
- return InCallState.STARTING_UP;
+ // 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. Because the previous state was
+ // not INCOMING (and you can't have two incoming calls at once),
+ // we start the start-up sequence by setting
+ // InCallState = STARTING_UP (this is the code that you see
+ // below). During the STARTING_UP phase, InCallPresenter will
+ // ignore all new call changes that come in.
+ // 4) StatusBarNotifier - Listens to InCallState changes. When it sees STARTING_UP, it
+ // will 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.
+ // 6) InCallPresenter - Sets STARTED as the new InCallState and issues a manual update
+ // of the call list so that it catches any changes that it
+ // previously ignored during STARTING_UP. That will result
+ // in a recalculated InCallState and throw us back into this
+ // method again.
+ // 7) InCallPresenter - 99% of the time we end up back here with the current
+ // state at STARTED and newState as INCOMING (again). We do not
+ // want to do the start-up sequence again if we see that it has
+ // already STARTED so we just fall through in that case and let
+ // normal code flow occur (newState <= INCOMING).
+ //
+ // [ 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 &&
+ InCallState.STARTED != mInCallState);
+
+ // 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);
+
+ Logger.v(this, "showCallUi: ", showCallUi);
+ Logger.v(this, "startStartupSequence: ", startStartupSequence);
+
+
+ if (startStartupSequence) {
+ return InCallState.STARTING_UP;
+ } else if (showCallUi) {
+ showInCall();
+ } else if (newState == InCallState.HIDDEN) {
+
+ // The new state is the hidden state (no calls). Tear everything down.
+
+ if (mInCallActivity != null) {
+ // Null out reference before we start end sequence
+ InCallActivity temp = mInCallActivity;
+ mInCallActivity = null;
+
+ temp.finish();
}
-
- } else if (mInCallActivity != null) {
- // Null out reference before we start end sequence
- InCallActivity temp = mInCallActivity;
- mInCallActivity = null;
-
- temp.finish();
}
return newState;
}
+ private void showInCall() {
+ Logger.d(this, "Showing in call manually.");
+ mContext.startActivity(getInCallIntent());
+ }
+
+ private Intent getInCallIntent() {
+ final Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
+ intent.setClass(mContext, InCallActivity.class);
+
+ return intent;
+ }
+
/**
* Private constructor. Must use getInstance() to get this singleton.
*/
private InCallPresenter(Context context) {
Preconditions.checkNotNull(context);
+ mContext = context;
+
mStatusBarNotifier = new StatusBarNotifier(context);
addListener(mStatusBarNotifier);