From f003346e5f9ba29e869a881bcca2e59d6ea8e0f6 Mon Sep 17 00:00:00 2001 From: Nancy Chen Date: Thu, 31 Jul 2014 16:33:35 -0700 Subject: Reduce latency for InCallUI by adding an intermediate state Add PENDING_OUTGOING as a state where the Telecomm information has not yet returned but the UI has started. This allows the UI to immediately begin initiating while Telecomm is waiting for the return of its broadcast intent. Bug: 16396523 Change-Id: Ia4b39689b89f9dea3aafae9e63ca0bfebb730501 --- InCallUI/src/com/android/incallui/Call.java | 10 ++++-- .../com/android/incallui/CallButtonPresenter.java | 19 +++++------- .../src/com/android/incallui/CallCardFragment.java | 6 ++++ .../com/android/incallui/CallCardPresenter.java | 24 +++++++++------ InCallUI/src/com/android/incallui/CallList.java | 7 +++++ .../incallui/ConferenceManagerPresenter.java | 6 ++-- .../src/com/android/incallui/DialpadPresenter.java | 3 +- .../src/com/android/incallui/InCallPresenter.java | 36 ++++++++++++++++------ .../src/com/android/incallui/ProximitySensor.java | 6 ++-- .../com/android/incallui/StatusBarNotifier.java | 4 +-- .../com/android/incallui/VideoCallPresenter.java | 18 ++++++----- 11 files changed, 90 insertions(+), 49 deletions(-) (limited to 'InCallUI') diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java index 9b983220a..fcdf09223 100644 --- a/InCallUI/src/com/android/incallui/Call.java +++ b/InCallUI/src/com/android/incallui/Call.java @@ -46,12 +46,14 @@ public final class Call { public static final int DISCONNECTED = 9; /* State after a call disconnects */ public static final int CONFERENCED = 10; /* Call part of a conference call */ public static final int PRE_DIAL_WAIT = 11; /* Waiting for user before outgoing call */ + public static final int CONNECTING = 12; /* Waiting for Telecomm broadcast to finish */ - public static boolean isConnected(int state) { + public static boolean isConnectingOrConnected(int state) { switch(state) { case ACTIVE: case INCOMING: case CALL_WAITING: + case CONNECTING: case DIALING: case REDIALING: case ONHOLD: @@ -92,8 +94,10 @@ public final class Call { return "CONFERENCED"; case PRE_DIAL_WAIT: return "PRE_DIAL_WAIT"; + case CONNECTING: + return "CONNECTING"; default: - return "UNKOWN"; + return "UNKNOWN"; } } } @@ -222,6 +226,8 @@ public final class Call { private static int translateState(int state) { switch (state) { + case android.telecomm.Call.STATE_CONNECTING: + return Call.State.CONNECTING; case android.telecomm.Call.STATE_PRE_DIAL_WAIT: return Call.State.PRE_DIAL_WAIT; case android.telecomm.Call.STATE_DIALING: diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java index 15a64b63f..7ecdc6fad 100644 --- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java +++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java @@ -41,7 +41,6 @@ public class CallButtonPresenter extends Presenter } @Override - public void onIncomingCall(InCallState state, Call call) { + public void onIncomingCall(InCallState oldState, InCallState newState, Call call) { // same logic should happen as with onStateChange() - onStateChange(state, CallList.getInstance()); + onStateChange(oldState, newState, CallList.getInstance()); } @Override - public void onStateChange(InCallState state, CallList callList) { - Log.d(this, "onStateChange() " + state); + public void onStateChange(InCallState oldState, InCallState newState, CallList callList) { + Log.d(this, "onStateChange() " + newState); final CallCardUi ui = getUi(); if (ui == null) { return; @@ -175,15 +175,18 @@ public class CallCardPresenter extends Presenter Call primary = null; Call secondary = null; - if (state == InCallState.INCOMING) { + if (newState == InCallState.INCOMING) { primary = callList.getIncomingCall(); - } else if (state == InCallState.OUTGOING) { + } else if (newState == InCallState.PENDING_OUTGOING || newState == InCallState.OUTGOING) { primary = callList.getOutgoingCall(); + if (primary == null) { + primary = callList.getPendingOutgoingCall(); + } // getCallToDisplay doesn't go through outgoing or incoming calls. It will return the // highest priority call to display as the secondary call. secondary = getCallToDisplay(callList, null, true); - } else if (state == InCallState.INCALL) { + } else if (newState == InCallState.INCALL) { primary = getCallToDisplay(callList, null, false); secondary = getCallToDisplay(callList, primary, true); } @@ -191,7 +194,9 @@ public class CallCardPresenter extends Presenter Log.d(this, "Primary call: " + primary); Log.d(this, "Secondary call: " + secondary); - final boolean primaryChanged = !areCallsSame(mPrimary, primary); + final boolean outgoingCallReady = newState == InCallState.OUTGOING && + oldState == InCallState.PENDING_OUTGOING; + final boolean primaryChanged = !areCallsSame(mPrimary, primary) || outgoingCallReady; final boolean secondaryChanged = !areCallsSame(mSecondary, secondary); mSecondary = secondary; mPrimary = primary; @@ -265,7 +270,7 @@ public class CallCardPresenter extends Presenter getUi().setPhotoVisible(!(mPrimary.isVideoCall() && callState != Call.State.ONHOLD)); } - final boolean enableEndCallButton = Call.State.isConnected(callState) && + final boolean enableEndCallButton = Call.State.isConnectingOrConnected(callState) && callState != Call.State.INCOMING && mPrimary != null; getUi().setEndCallButtonEnabled(enableEndCallButton); } @@ -437,6 +442,7 @@ public class CallCardPresenter extends Presenter if (getUi() == null) { return; } + if (entry.photo != null) { if (mPrimary != null && callId.equals(mPrimary.getId())) { getUi().setPrimaryImage(entry.photo); diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java index 127c04a17..becb411ca 100644 --- a/InCallUI/src/com/android/incallui/CallList.java +++ b/InCallUI/src/com/android/incallui/CallList.java @@ -204,6 +204,10 @@ public class CallList implements InCallPhoneListener { return getFirstCallWithState(Call.State.PRE_DIAL_WAIT); } + public Call getPendingOutgoingCall() { + return getFirstCallWithState(Call.State.CONNECTING); + } + public Call getOutgoingCall() { Call call = getFirstCallWithState(Call.State.DIALING); if (call == null) { @@ -251,6 +255,9 @@ public class CallList implements InCallPhoneListener { public Call getFirstCall() { Call result = getIncomingCall(); + if (result == null) { + result = getPendingOutgoingCall(); + } if (result == null) { result = getOutgoingCall(); } diff --git a/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java b/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java index b505e29f4..2b5e8eb90 100644 --- a/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java +++ b/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java @@ -53,10 +53,10 @@ public class ConferenceManagerPresenter } @Override - public void onStateChange(InCallState state, CallList callList) { + public void onStateChange(InCallState oldState, InCallState newState, CallList callList) { if (getUi().isFragmentVisible()) { - Log.v(this, "onStateChange" + state); - if (state == InCallState.INCALL) { + Log.v(this, "onStateChange" + newState); + if (newState == InCallState.INCALL) { final Call call = callList.getActiveOrBackgroundCall(); if (call != null && call.isConferenceCall()) { Log.v(this, "Number of existing calls is " + diff --git a/InCallUI/src/com/android/incallui/DialpadPresenter.java b/InCallUI/src/com/android/incallui/DialpadPresenter.java index 79fe3d6df..f612a7384 100644 --- a/InCallUI/src/com/android/incallui/DialpadPresenter.java +++ b/InCallUI/src/com/android/incallui/DialpadPresenter.java @@ -39,7 +39,8 @@ public class DialpadPresenter extends Presenter } @Override - public void onStateChange(InCallPresenter.InCallState state, CallList callList) { + public void onStateChange(InCallPresenter.InCallState oldState, + InCallPresenter.InCallState newState, CallList callList) { mCall = callList.getActiveCall(); Log.d(this, "DialpadPresenter mCall = " + mCall); } diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java index 6d7e5b810..cf43fbd66 100644 --- a/InCallUI/src/com/android/incallui/InCallPresenter.java +++ b/InCallUI/src/com/android/incallui/InCallPresenter.java @@ -311,16 +311,17 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { return; } InCallState newState = getPotentialStateFromCallList(callList); + InCallState oldState = mInCallState; newState = startOrFinishUi(newState); // Set the new state before announcing it to the world - Log.i(this, "Phone switching state: " + mInCallState + " -> " + newState); + Log.i(this, "Phone switching state: " + oldState + " -> " + newState); mInCallState = newState; // notify listeners of new state for (InCallStateListener listener : mListeners) { Log.d(this, "Notify " + listener + " of state " + mInCallState.toString()); - listener.onStateChange(mInCallState, callList); + listener.onStateChange(oldState, mInCallState, callList); } if (isActivityStarted()) { @@ -338,12 +339,13 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { @Override public void onIncomingCall(Call call) { InCallState newState = startOrFinishUi(InCallState.INCOMING); + InCallState oldState = mInCallState; - Log.i(this, "Phone switching state: " + mInCallState + " -> " + newState); + Log.i(this, "Phone switching state: " + oldState + " -> " + newState); mInCallState = newState; for (IncomingCallListener listener : mIncomingCallListeners) { - listener.onIncomingCall(mInCallState, call); + listener.onIncomingCall(oldState, mInCallState, call); } } @@ -378,6 +380,8 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { newState = InCallState.INCOMING; } else if (callList.getWaitingForAccountCall() != null) { newState = InCallState.WAITING_FOR_ACCOUNT; + } else if (callList.getPendingOutgoingCall() != null) { + newState = InCallState.PENDING_OUTGOING; } else if (callList.getOutgoingCall() != null) { newState = InCallState.OUTGOING; } else if (callList.getActiveCall() != null || @@ -714,9 +718,12 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { // 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) { + // If the state isn't changing or if we're transitioning from pending outgoing to actual + // outgoing, we have already done any starting/stopping of activities in a previous pass + // ...so lets cut out early + boolean alreadyOutgoing = mInCallState == InCallState.PENDING_OUTGOING && + newState == InCallState.OUTGOING; + if (newState == mInCallState || alreadyOutgoing) { return newState; } @@ -753,9 +760,14 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { // happens we need to display the screen immediately or show an account picker dialog if // no default is set. // + // It is also possible to go into an intermediate state where the call has been initiated + // but Telecomm has not yet returned with the details of the call (handle, gateway, etc.). + // This pending outgoing state also launches the call screen. + // // 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 || showAccountPicker); + final boolean showCallUi = ((InCallState.PENDING_OUTGOING == newState || + InCallState.OUTGOING == newState) || showAccountPicker); // 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. @@ -985,6 +997,10 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { // Waiting for user input before placing outgoing call WAITING_FOR_ACCOUNT, + // UI is starting up but no call has been initiated yet. + // The UI is waiting for Telecomm to respond. + PENDING_OUTGOING, + // User is dialing out OUTGOING; @@ -1004,11 +1020,11 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener { */ public interface InCallStateListener { // TODO: Enhance state to contain the call objects instead of passing CallList - public void onStateChange(InCallState state, CallList callList); + public void onStateChange(InCallState oldState, InCallState newState, CallList callList); } public interface IncomingCallListener { - public void onIncomingCall(InCallState state, Call call); + public void onIncomingCall(InCallState oldState, InCallState newState, Call call); } public interface InCallDetailsListener { diff --git a/InCallUI/src/com/android/incallui/ProximitySensor.java b/InCallUI/src/com/android/incallui/ProximitySensor.java index 768a71478..6f69096a6 100644 --- a/InCallUI/src/com/android/incallui/ProximitySensor.java +++ b/InCallUI/src/com/android/incallui/ProximitySensor.java @@ -80,11 +80,11 @@ public class ProximitySensor implements AccelerometerListener.OrientationListene * Called to keep track of the overall UI state. */ @Override - public void onStateChange(InCallState state, CallList callList) { + public void onStateChange(InCallState oldState, InCallState newState, CallList callList) { // We ignore incoming state because we do not want to enable proximity // sensor during incoming call screen - boolean isOffhook = (InCallState.INCALL == state - || InCallState.OUTGOING == state); + boolean isOffhook = (InCallState.INCALL == newState + || InCallState.OUTGOING == newState); if (isOffhook != mIsPhoneOffhook) { mIsPhoneOffhook = isOffhook; diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java index f2f883a9e..f88d2b5c6 100644 --- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java +++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java @@ -109,10 +109,10 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { * Creates notifications according to the state we receive from {@link InCallPresenter}. */ @Override - public void onStateChange(InCallState state, CallList callList) { + public void onStateChange(InCallState oldState, InCallState newState, CallList callList) { Log.d(this, "onStateChange"); - updateNotification(state, callList); + updateNotification(newState, callList); } /** diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java index 77aa4ac0c..7ff591f47 100644 --- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java +++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java @@ -277,30 +277,32 @@ public class VideoCallPresenter extends Presenter