summaryrefslogtreecommitdiff
path: root/InCallUI/src/com/android/incallui/InCallPresenter.java
diff options
context:
space:
mode:
Diffstat (limited to 'InCallUI/src/com/android/incallui/InCallPresenter.java')
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java261
1 files changed, 136 insertions, 125 deletions
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 078dd49ce..d5aa0e500 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -16,7 +16,7 @@
package com.android.incallui;
-import android.app.Activity;
+import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -24,7 +24,6 @@ import android.content.res.Resources;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.Phone;
@@ -41,6 +40,7 @@ import android.view.WindowManager;
import com.google.common.base.Preconditions;
import com.android.contacts.common.interactions.TouchPointManager;
+import com.android.contacts.common.testing.NeededForTesting;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.incalluibind.ObjectFactory;
@@ -60,7 +60,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
* that want to listen in on the in-call state changes.
* TODO: This class has become more of a state machine at this point. Consider renaming.
*/
-public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
+public class InCallPresenter implements CallList.Listener, InCallPhoneListener,
+ CircularRevealFragment.OnCircularRevealCompleteListener {
private static final String EXTRA_FIRST_TIME_SHOWN =
"com.android.incallui.intent.extra.FIRST_TIME_SHOWN";
@@ -99,6 +100,17 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
private boolean mServiceConnected = false;
private boolean mAccountSelectionCancelled = false;
private InCallCameraManager mInCallCameraManager = null;
+ private AnswerPresenter mAnswerPresenter = new AnswerPresenter();
+
+ /**
+ * Whether or not we are currently bound and waiting for Telecom to send us a new call.
+ */
+ private boolean mBoundAndWaitingForOutgoingCall;
+ /**
+ * If there is no actual call currently in the call list, this will be used as a fallback
+ * to determine the theme color for InCallUI.
+ */
+ private PhoneAccountHandle mPendingPhoneAccountHandle;
private final Phone.Listener mPhoneListener = new Phone.Listener() {
@Override
@@ -108,6 +120,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
@Override
public void onCallAdded(Phone phone, android.telecom.Call call) {
+ // Since a call has been added we are no longer waiting for Telecom to send us a
+ // call.
+ setBoundAndWaitingForOutgoingCall(false, null);
call.addListener(mCallListener);
}
@Override
@@ -126,8 +141,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
new android.telecom.Call.Listener() {
@Override
public void onPostDialWait(android.telecom.Call call, String remainingPostDialSequence) {
- onPostDialCharWait(
- CallList.getInstance().getCallByTelecommCall(call).getId(),
+ onPostDialCharWait(mCallList.getCallByTelecommCall(call).getId(),
remainingPostDialSequence);
}
@@ -135,7 +149,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
public void onDetailsChanged(android.telecom.Call call,
android.telecom.Call.Details details) {
for (InCallDetailsListener listener : mDetailsListeners) {
- listener.onDetailsChanged(CallList.getInstance().getCallByTelecommCall(call),
+ listener.onDetailsChanged(mCallList.getCallByTelecommCall(call),
details);
}
}
@@ -145,7 +159,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
android.telecom.Call call, List<android.telecom.Call> conferenceableCalls) {
Log.i(this, "onConferenceableCallsChanged: " + call);
for (InCallDetailsListener listener : mDetailsListeners) {
- listener.onDetailsChanged(CallList.getInstance().getCallByTelecommCall(call),
+ listener.onDetailsChanged(mCallList.getCallByTelecommCall(call),
call.getDetails());
}
}
@@ -160,19 +174,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
private boolean mIsActivityPreviouslyStarted = false;
/**
- * Whether or not to wait for the circular reveal animation to be started, to avoid stopping
- * the circular reveal animation activity before the animation is initiated.
- */
- private boolean mWaitForRevealAnimationStart = false;
-
- /**
- * Whether or not the CircularRevealAnimationActivity has started.
- */
- private boolean mCircularRevealActivityStarted = false;
-
- private boolean mShowDialpadOnStart = false;
-
- /**
* Whether or not InCallService is bound to Telecom.
*/
private boolean mServiceBound = false;
@@ -187,8 +188,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
private Phone mPhone;
- private Handler mHandler = new Handler();
-
/** Display colors for the UI. Consists of a primary color and secondary (darker) color */
private MaterialPalette mThemeColors;
@@ -201,6 +200,11 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return sInCallPresenter;
}
+ @NeededForTesting
+ static synchronized void setInstance(InCallPresenter inCallPresenter) {
+ sInCallPresenter = inCallPresenter;
+ }
+
@Override
public void setPhone(Phone phone) {
mPhone = phone;
@@ -221,7 +225,12 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return mCallList;
}
- public void setUp(Context context, CallList callList, AudioModeProvider audioModeProvider) {
+ public void setUp(Context context,
+ CallList callList,
+ AudioModeProvider audioModeProvider,
+ StatusBarNotifier statusBarNotifier,
+ ContactInfoCache contactInfoCache,
+ ProximitySensor proximitySensor) {
if (mServiceConnected) {
Log.i(this, "New service connection replacing existing one.");
// retain the current resources, no need to create new ones.
@@ -234,14 +243,14 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
Preconditions.checkNotNull(context);
mContext = context;
- mContactInfoCache = ContactInfoCache.getInstance(context);
+ mContactInfoCache = contactInfoCache;
- mStatusBarNotifier = new StatusBarNotifier(context, mContactInfoCache);
+ mStatusBarNotifier = statusBarNotifier;
addListener(mStatusBarNotifier);
mAudioModeProvider = audioModeProvider;
- mProximitySensor = new ProximitySensor(context, mAudioModeProvider);
+ mProximitySensor = proximitySensor;
addListener(mProximitySensor);
mCallList = callList;
@@ -275,13 +284,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
private void attemptFinishActivity() {
- mWaitForRevealAnimationStart = false;
-
- Context context = mContext != null ? mContext : mInCallActivity;
- if (context != null) {
- CircularRevealActivity.sendClearDisplayBroadcast(context);
- }
-
final boolean doFinish = (mInCallActivity != null && isActivityStarted());
Log.i(this, "Hide in call UI: " + doFinish);
if (doFinish) {
@@ -401,6 +403,8 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
}
+ private boolean mAwaitingCallListUpdate = false;
+
/**
* Called when there is a change to the call list.
* Sets the In-Call state for the entire in-call app based on the information it gets from
@@ -409,10 +413,17 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
@Override
public void onCallListChange(CallList callList) {
+ if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null &&
+ mInCallActivity.getCallCardFragment().isAnimating()) {
+ mAwaitingCallListUpdate = true;
+ return;
+ }
if (callList == null) {
return;
}
- Log.d(this, "onCallListChange callList=" + callList.toString() );
+
+ mAwaitingCallListUpdate = false;
+
InCallState newState = getPotentialStateFromCallList(callList);
InCallState oldState = mInCallState;
Log.d(this, "onCallListChange oldState= " + oldState + " newState=" + newState);
@@ -464,11 +475,10 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
@Override
public void onDisconnect(Call call) {
- hideDialpadForDisconnect();
maybeShowErrorDialogOnDisconnect(call);
// We need to do the run the same code as onCallListChange.
- onCallListChange(CallList.getInstance());
+ onCallListChange(mCallList);
if (isActivityStarted()) {
mInCallActivity.dismissKeyguard(false);
@@ -478,7 +488,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
/**
* Given the call list, return the state in which the in-call screen should be.
*/
- public static InCallState getPotentialStateFromCallList(CallList callList) {
+ public InCallState getPotentialStateFromCallList(CallList callList) {
InCallState newState = InCallState.NO_CALLS;
@@ -500,9 +510,47 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
newState = InCallState.INCALL;
}
+ if (newState == InCallState.NO_CALLS) {
+ if (mBoundAndWaitingForOutgoingCall) {
+ return InCallState.OUTGOING;
+ }
+ }
+
return newState;
}
+ public boolean isBoundAndWaitingForOutgoingCall() {
+ return mBoundAndWaitingForOutgoingCall;
+ }
+
+ public void setBoundAndWaitingForOutgoingCall(boolean isBound, PhoneAccountHandle handle) {
+ // NOTE: It is possible for there to be a race and have handle become null before
+ // the circular reveal starts. This should not cause any problems because CallCardFragment
+ // should fallback to the actual call in the CallList at that point in time to determine
+ // the theme color.
+ Log.i(this, "setBoundAndWaitingForOutgoingCall: " + isBound);
+ mBoundAndWaitingForOutgoingCall = isBound;
+ mPendingPhoneAccountHandle = handle;
+ if (isBound && mInCallState == InCallState.NO_CALLS) {
+ mInCallState = InCallState.OUTGOING;
+ }
+ }
+
+ @Override
+ public void onCircularRevealComplete(FragmentManager fm) {
+ if (mInCallActivity != null) {
+ mInCallActivity.showCallCardFragment(true);
+ mInCallActivity.getCallCardFragment().animateForNewOutgoingCall();
+ CircularRevealFragment.endCircularReveal(mInCallActivity.getFragmentManager());
+ }
+ }
+
+ public void onShrinkAnimationComplete() {
+ if (mAwaitingCallListUpdate) {
+ onCallListChange(mCallList);
+ }
+ }
+
public void addIncomingCallListener(IncomingCallListener listener) {
Preconditions.checkNotNull(listener);
mIncomingCallListeners.add(listener);
@@ -574,19 +622,23 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public void handleAccountSelection(PhoneAccountHandle accountHandle, boolean setDefault) {
- Call call = mCallList.getWaitingForAccountCall();
- if (call != null) {
- String callId = call.getId();
- TelecomAdapter.getInstance().phoneAccountSelected(callId, accountHandle, setDefault);
+ if (mCallList != null) {
+ Call call = mCallList.getWaitingForAccountCall();
+ if (call != null) {
+ String callId = call.getId();
+ TelecomAdapter.getInstance().phoneAccountSelected(callId, accountHandle, setDefault);
+ }
}
}
public void cancelAccountSelection() {
mAccountSelectionCancelled = true;
- Call call = mCallList.getWaitingForAccountCall();
- if (call != null) {
- String callId = call.getId();
- TelecomAdapter.getInstance().disconnectCall(callId);
+ if (mCallList != null) {
+ Call call = mCallList.getWaitingForAccountCall();
+ if (call != null) {
+ String callId = call.getId();
+ TelecomAdapter.getInstance().disconnectCall(callId);
+ }
}
}
@@ -753,7 +805,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
if (showing) {
mIsActivityPreviouslyStarted = true;
} else {
- CircularRevealActivity.sendClearDisplayBroadcast(mContext);
updateIsChangingConfigurations();
}
@@ -826,7 +877,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
/**
* INCOMING CALL
*/
- final CallList calls = CallList.getInstance();
+ final CallList calls = mCallList;
final Call incomingCall = calls.getIncomingCall();
Log.v(this, "incomingCall: " + incomingCall);
@@ -923,15 +974,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
/**
- * Hides the dialpad. Called when a call is disconnected (Requires hiding dialpad).
- */
- private void hideDialpadForDisconnect() {
- if (isActivityStarted()) {
- mInCallActivity.hideDialpadForDisconnect();
- }
- }
-
- /**
* 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.
*/
@@ -969,8 +1011,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
// [ 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);
+ // we get an incoming call. Depending on the current context of the device, either a
+ // incoming call HUN or the actual InCallActivity will be shown.
+ final boolean startIncomingCallSequence = (InCallState.INCOMING == newState);
// A dialog to show on top of the InCallUI to select a PhoneAccount
final boolean showAccountPicker = (InCallState.WAITING_FOR_ACCOUNT == newState);
@@ -1003,7 +1046,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
// machine. Telecom should also be the component responsible for disconnecting a call
// with no valid accounts.
showCallUi |= InCallState.PENDING_OUTGOING == newState && mainUiNotVisible
- && isCallWithNoValidAccounts(CallList.getInstance().getPendingOutgoingCall());
+ && isCallWithNoValidAccounts(mCallList.getPendingOutgoingCall());
// 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
@@ -1018,7 +1061,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
if (showCallUi || showAccountPicker) {
Log.i(this, "Start in call UI");
showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);
- } else if (startStartupSequence) {
+ } else if (startIncomingCallSequence) {
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
@@ -1052,7 +1095,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
public static boolean isCallWithNoValidAccounts(Call call) {
if (call != null && !isEmergencyCall(call)) {
- Bundle extras = call.getTelecommCall().getDetails().getExtras();
+ Bundle extras = call.getExtras();
if (extras == null) {
extras = EMPTY_EXTRAS;
@@ -1189,41 +1232,8 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public void showInCall(final boolean showDialpad, final boolean newOutgoingCall) {
- if (mCircularRevealActivityStarted) {
- mWaitForRevealAnimationStart = true;
- mShowDialpadOnStart = showDialpad;
- Log.i(this, "Waiting for circular reveal completion to show InCallActivity");
- } else {
- Log.i(this, "Showing InCallActivity immediately");
- mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall,
- newOutgoingCall /* showCircularReveal */));
- }
- }
-
- public void onCircularRevealStarted(final Activity activity) {
- mCircularRevealActivityStarted = false;
- if (mWaitForRevealAnimationStart) {
- mWaitForRevealAnimationStart = false;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mContext == null) {
- Log.e(this, "Setup did not occur before showing the InCallActivity.");
- activity.finish();
- return;
- }
-
- Log.i(this, "Showing InCallActivity after circular reveal");
- final Intent intent =
- getInCallIntent(mShowDialpadOnStart, true, false, false);
- activity.startActivity(intent);
- mShowDialpadOnStart = false;
- }
- });
- } else if (!mServiceBound) {
- CircularRevealActivity.sendClearDisplayBroadcast(mContext);
- return;
- }
+ Log.i(this, "Showing InCallActivity");
+ mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall));
}
public void onServiceBind() {
@@ -1231,6 +1241,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public void onServiceUnbind() {
+ InCallPresenter.getInstance().setBoundAndWaitingForOutgoingCall(false, null);
mServiceBound = false;
}
@@ -1255,43 +1266,26 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
final PhoneAccountHandle accountHandle =
intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
- final MaterialPalette colors = getColorsFromPhoneAccountHandle(accountHandle);
final Point touchPoint = extras.getParcelable(TouchPointManager.TOUCH_POINT);
- mCircularRevealActivityStarted = true;
- mContext.startActivity(getAnimationIntent(touchPoint, colors));
- }
+ InCallPresenter.getInstance().setBoundAndWaitingForOutgoingCall(true, accountHandle);
- private Intent getAnimationIntent(Point touchPoint, MaterialPalette palette) {
- final Intent intent = new Intent(mContext, CircularRevealActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- intent.putExtra(TouchPointManager.TOUCH_POINT, touchPoint);
- intent.putExtra(CircularRevealActivity.EXTRA_THEME_COLORS, palette);
- return intent;
+ final Intent incallIntent = getInCallIntent(false, true);
+ incallIntent.putExtra(TouchPointManager.TOUCH_POINT, touchPoint);
+ mContext.startActivity(incallIntent);
}
- public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall,
- boolean showCircularReveal) {
- return getInCallIntent(showDialpad, newOutgoingCall, showCircularReveal, true);
- }
-
- public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall,
- boolean showCircularReveal, boolean newTask) {
+ public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall) {
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- if (newTask) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- }
+ | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(mContext, InCallActivity.class);
if (showDialpad) {
intent.putExtra(InCallActivity.SHOW_DIALPAD_EXTRA, true);
}
intent.putExtra(InCallActivity.NEW_OUTGOING_CALL_EXTRA, newOutgoingCall);
- intent.putExtra(InCallActivity.SHOW_CIRCULAR_REVEAL_EXTRA, showCircularReveal);
return intent;
}
@@ -1401,7 +1395,10 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
* @return The space beside the call card.
*/
public float getSpaceBesideCallCard() {
- return mInCallActivity.getCallCardFragment().getSpaceBesideCallCard();
+ if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null) {
+ return mInCallActivity.getCallCardFragment().getSpaceBesideCallCard();
+ }
+ return 0;
}
/**
@@ -1410,7 +1407,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
* @return True if the call card fragment is visible.
*/
public boolean getCallCardFragmentVisible() {
- if (mInCallActivity != null) {
+ if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null) {
return mInCallActivity.getCallCardFragment().isVisible();
}
return false;
@@ -1427,7 +1424,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return;
}
- mInCallActivity.showConferenceCallManager(show);
+ mInCallActivity.showConferenceFragment(show);
}
/**
@@ -1444,7 +1441,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
public void setThemeColors() {
// This method will set the background to default if the color is PhoneAccount.NO_COLOR.
- mThemeColors = getColorsFromCall(CallList.getInstance().getFirstCall());
+ mThemeColors = getColorsFromCall(mCallList.getFirstCall());
if (mInCallActivity == null) {
return;
@@ -1467,7 +1464,11 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
private MaterialPalette getColorsFromCall(Call call) {
- return getColorsFromPhoneAccountHandle(call == null ? null : call.getAccountHandle());
+ if (call == null) {
+ return getColorsFromPhoneAccountHandle(mPendingPhoneAccountHandle);
+ } else {
+ return getColorsFromPhoneAccountHandle(call.getAccountHandle());
+ }
}
private MaterialPalette getColorsFromPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
@@ -1499,10 +1500,20 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return mTelecomManager;
}
+ InCallActivity getActivity() {
+ return mInCallActivity;
+ }
+
+ AnswerPresenter getAnswerPresenter() {
+ return mAnswerPresenter;
+ }
+
/**
* Private constructor. Must use getInstance() to get this singleton.
*/
private InCallPresenter() {
+ addIncomingCallListener(mAnswerPresenter);
+ addInCallUiListener(mAnswerPresenter);
}
/**