diff options
Diffstat (limited to 'InCallUI/src/com/android/incallui/InCallPresenter.java')
-rw-r--r-- | InCallUI/src/com/android/incallui/InCallPresenter.java | 261 |
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); } /** |