diff options
3 files changed, 82 insertions, 8 deletions
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java index 8ae37bd21..c76f08ad0 100644 --- a/InCallUI/src/com/android/incallui/InCallActivity.java +++ b/InCallUI/src/com/android/incallui/InCallActivity.java @@ -34,6 +34,7 @@ public class InCallActivity extends Activity { private CallCardFragment mCallCardFragment; private AnswerFragment mAnswerFragment; private DialpadFragment mDialpadFragment; + private boolean mIsForegroundActivity; @Override protected void onCreate(Bundle icicle) { @@ -62,6 +63,9 @@ public class InCallActivity extends Activity { protected void onResume() { Logger.d(this, "onResume()..."); super.onResume(); + + mIsForegroundActivity = true; + InCallPresenter.getInstance().onUiShowing(true); } // onPause is guaranteed to be called when the InCallActivity goes @@ -70,6 +74,9 @@ public class InCallActivity extends Activity { protected void onPause() { Logger.d(this, "onPause()..."); super.onPause(); + + mIsForegroundActivity = false; + InCallPresenter.getInstance().onUiShowing(false); } @Override @@ -85,6 +92,13 @@ public class InCallActivity extends Activity { } /** + * Returns true when theActivity is in foreground (between onResume and onPause). + */ + /* package */ boolean isForegroundActivity() { + return mIsForegroundActivity; + } + + /** * Dismisses the in-call screen. * * We never *really* finish() the InCallActivity, since we don't want to get destroyed and then diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java index c56d980ea..5f1129b79 100644 --- a/InCallUI/src/com/android/incallui/InCallPresenter.java +++ b/InCallUI/src/com/android/incallui/InCallPresenter.java @@ -163,6 +163,23 @@ public class InCallPresenter implements CallList.Listener { } /** + * Returns true if the incall app is the foreground application. + */ + public boolean isShowingInCallUi() { + return (mInCallActivity != null && + mInCallActivity.isForegroundActivity()); + } + + /** + * Called when the activity goes out of the foreground. + */ + public void onUiShowing(boolean showing) { + // We need to update the notification bar when we leave the UI because that + // could trigger it to show again. + mStatusBarNotifier.updateNotification(mInCallState); + } + + /** * 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. */ diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java index 857b6ce24..451d04269 100644 --- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java +++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java @@ -37,6 +37,7 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { private final Context mContext; private final NotificationManager mNotificationManager; + private boolean mIsShowingNotification = false; private InCallState mInCallState = InCallState.HIDDEN; public StatusBarNotifier(Context context) { @@ -52,7 +53,7 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { */ @Override public void onStateChange(InCallState state, CallList callList) { - updateInCallNotification(state); + updateNotification(state); } /** @@ -63,7 +64,7 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { * This method will never actually launch the incoming-call UI. * (Use updateNotificationAndLaunchIncomingCallUi() for that.) */ - private void updateInCallNotification(InCallState state) { + public void updateNotification(InCallState state) { // allowFullScreenIntent=false means *don't* allow the incoming // call UI to be launched. updateInCallNotification(false, state); @@ -114,6 +115,8 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { private void cancelInCall() { Logger.d(this, "cancelInCall()..."); mNotificationManager.cancel(IN_CALL_NOTIFICATION); + + mIsShowingNotification = false; } /** @@ -133,17 +136,18 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { Logger.d(this, "updateInCallNotification(allowFullScreenIntent = " + allowFullScreenIntent + ")..."); - // First, we dont need to continue issuing new notifications if the state hasn't - // changed from the last time we did this. - if (mInCallState == state) { + if (shouldSuppressNotification(state)) { + cancelInCall(); return; } - mInCallState = state; - if (!state.isConnectingOrConnected()) { - cancelInCall(); + // We dont need to continue issuing new notifications if the state hasn't + // changed from the last time we did this and we're still showing the same + // notification + if (mInCallState == state && mIsShowingNotification) { return; } + mInCallState = state; final PendingIntent inCallPendingIntent = createLaunchPendingIntent(); final Notification.Builder builder = getNotificationBuilder(); @@ -167,6 +171,7 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { Notification notification = builder.build(); Logger.d(this, "Notifying IN_CALL_NOTIFICATION: " + notification); mNotificationManager.notify(IN_CALL_NOTIFICATION, notification); + mIsShowingNotification = true; } /** @@ -246,6 +251,44 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener { return builder; } + /** + * Returns true if notification should not be shown in the current state. + */ + private boolean shouldSuppressNotification(InCallState state) { + // Suppress the in-call notification if the InCallScreen is the + // foreground activity, since it's already obvious that you're on a + // call. (The status bar icon is needed only if you navigate *away* + // from the in-call UI.) + boolean shouldSuppress = InCallPresenter.getInstance().isShowingInCallUi(); + + // Suppress if the call is not active. + shouldSuppress |= !state.isConnectingOrConnected(); + + // If there's an incoming ringing call: always show the + // notification, since the in-call notification is what actually + // launches the incoming call UI in the first place (see + // notification.fullScreenIntent below.) This makes sure that we'll + // correctly handle the case where a new incoming call comes in but + // the InCallScreen is already in the foreground. + if (state.isIncoming()) { + shouldSuppress = false; + } + + // JANK fix: + // This class will issue a notification when user makes an outgoing call. + // However, since we suppress the notification when the user is in the in-call screen, + // that results is us showing it for a split second, until the in-call screen comes up. + // It looks ugly. + // + // The solution is to ignore the change from HIDDEN to OUTGOING since in that particular + // case, we know we'll get called to update again when the UI finally starts. + if (InCallState.OUTGOING == state && InCallState.HIDDEN == mInCallState) { + shouldSuppress = true; + } + + return shouldSuppress; + } + private PendingIntent createLaunchPendingIntent() { final Intent intent = new Intent(Intent.ACTION_MAIN, null); |