summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--InCallUI/res/drawable-hdpi/stat_sys_phone_call.pngbin0 -> 1095 bytes
-rw-r--r--InCallUI/res/drawable-ldrtl-hdpi/stat_sys_phone_call.pngbin0 -> 4993 bytes
-rw-r--r--InCallUI/res/drawable-ldrtl-mdpi/stat_sys_phone_call.pngbin0 -> 4578 bytes
-rw-r--r--InCallUI/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.pngbin0 -> 5428 bytes
-rw-r--r--InCallUI/res/drawable-mdpi/stat_sys_phone_call.pngbin0 -> 796 bytes
-rw-r--r--InCallUI/res/drawable-xhdpi/stat_sys_phone_call.pngbin0 -> 1430 bytes
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonPresenter.java8
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java7
-rw-r--r--InCallUI/src/com/android/incallui/CallHandlerService.java4
-rw-r--r--InCallUI/src/com/android/incallui/CallList.java36
-rw-r--r--InCallUI/src/com/android/incallui/InCallActivity.java10
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java108
-rw-r--r--InCallUI/src/com/android/incallui/StatusBarNotifier.java267
13 files changed, 393 insertions, 47 deletions
diff --git a/InCallUI/res/drawable-hdpi/stat_sys_phone_call.png b/InCallUI/res/drawable-hdpi/stat_sys_phone_call.png
new file mode 100644
index 000000000..7eda84ca5
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/InCallUI/res/drawable-ldrtl-hdpi/stat_sys_phone_call.png b/InCallUI/res/drawable-ldrtl-hdpi/stat_sys_phone_call.png
new file mode 100644
index 000000000..e0f33f88c
--- /dev/null
+++ b/InCallUI/res/drawable-ldrtl-hdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/InCallUI/res/drawable-ldrtl-mdpi/stat_sys_phone_call.png b/InCallUI/res/drawable-ldrtl-mdpi/stat_sys_phone_call.png
new file mode 100644
index 000000000..d771d87bf
--- /dev/null
+++ b/InCallUI/res/drawable-ldrtl-mdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/InCallUI/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.png b/InCallUI/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.png
new file mode 100644
index 000000000..86af9c202
--- /dev/null
+++ b/InCallUI/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/stat_sys_phone_call.png b/InCallUI/res/drawable-mdpi/stat_sys_phone_call.png
new file mode 100644
index 000000000..70a4bbe71
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/stat_sys_phone_call.png b/InCallUI/res/drawable-xhdpi/stat_sys_phone_call.png
new file mode 100644
index 000000000..1bb434076
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index 014f8f8ae..60ab7bbf4 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -49,7 +49,7 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
getUi().setVisible(state == InCallState.INCALL);
if (state == InCallState.INCALL) {
- mCall = callList.getActiveCall();
+ mCall = callList.getActiveOrBackgroundCall();
} else {
mCall = null;
}
@@ -75,11 +75,15 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
}
public void muteClicked(boolean checked) {
+ Logger.d(this, "turning on mute: " + checked);
+
CallCommandClient.getInstance().mute(checked);
getUi().setMute(checked);
}
public void speakerClicked(boolean checked) {
+ Logger.d(this, "turning on speaker: " + checked);
+
CallCommandClient.getInstance().turnSpeakerOn(checked);
getUi().setSpeaker(checked);
}
@@ -87,6 +91,8 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
public void holdClicked(boolean checked) {
Preconditions.checkNotNull(mCall);
+ Logger.d(this, "holding: " + mCall.getCallId());
+
// TODO(klp): use appropriate hold callId.
CallCommandClient.getInstance().hold(mCall.getCallId(), checked);
getUi().setHold(checked);
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index 5f1f3b747..04a43eae1 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -43,7 +43,12 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
primary = callList.getIncomingCall();
} else if (state == InCallState.INCALL) {
primary = callList.getActiveCall();
- secondary = callList.getBackgroundCall();
+ if (primary != null) {
+ secondary = callList.getBackgroundCall();
+ } else {
+ primary = callList.getBackgroundCall();
+ secondary = callList.getSecondBackgroundCall();
+ }
}
Logger.d(this, "Primary call: " + primary);
diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java
index ad4772976..dcba7d6f9 100644
--- a/InCallUI/src/com/android/incallui/CallHandlerService.java
+++ b/InCallUI/src/com/android/incallui/CallHandlerService.java
@@ -46,9 +46,7 @@ public class CallHandlerService extends Service {
mCallList = CallList.getInstance();
mMainHandler = new MainHandler();
- mInCallPresenter = InCallPresenter.getInstance();
-
- mInCallPresenter.init(this);
+ mInCallPresenter = InCallPresenter.init(this);
}
@Override
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index 17e719e7c..c16c53df0 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -128,8 +128,25 @@ public class CallList {
return getFirstCallWithState(Call.State.ONHOLD);
}
+ public Call getSecondBackgroundCall() {
+ return getCallWithState(Call.State.ONHOLD, 1);
+ }
+
+ public Call getActiveOrBackgroundCall() {
+ Call call = getActiveCall();
+ if (call == null) {
+ call = getBackgroundCall();
+ }
+ return call;
+ }
+
public Call getIncomingCall() {
- return getFirstCallWithState(Call.State.INCOMING);
+ Call call = getFirstCallWithState(Call.State.INCOMING);
+ if (call == null) {
+ call = getFirstCallWithState(Call.State.CALL_WAITING);
+ }
+
+ return call;
}
public boolean existsLiveCall() {
@@ -145,11 +162,24 @@ public class CallList {
* Returns first call found in the call map with the specified state.
*/
public Call getFirstCallWithState(int state) {
+ return getCallWithState(state, 0);
+ }
+
+ /**
+ * Returns the [position]th call found in the call map with the specified state.
+ * TODO(klp): Improve this logic to sort by call time.
+ */
+ public Call getCallWithState(int state, int positionToFind) {
Call retval = null;
+ int position = 0;
for (Call call : mCallMap.values()) {
if (call.getState() == state) {
- retval = call;
- break;
+ if (position >= positionToFind) {
+ retval = call;
+ break;
+ } else {
+ position++;
+ }
}
}
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 89450c534..9eb54ee5e 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -101,6 +101,8 @@ public class InCallActivity extends Activity {
@Override
public void finish() {
Logger.d(this, "finish()...");
+ tearDownPresenters();
+
super.finish();
// TODO(klp): Actually finish the activity for now. Revisit performance implications of
@@ -220,6 +222,14 @@ public class InCallActivity extends Activity {
mainPresenter.setActivity(this);
}
+ private void tearDownPresenters() {
+ InCallPresenter mainPresenter = InCallPresenter.getInstance();
+
+ mainPresenter.removeListener(mCallButtonFragment.getPresenter());
+ mainPresenter.removeListener(mCallCardFragment.getPresenter());
+ mainPresenter.removeListener(mAnswerFragment.getPresenter());
+ }
+
private void toast(String text) {
final Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 118c030c2..47d2d69c8 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@ import com.google.common.base.Preconditions;
import android.content.Context;
import android.content.Intent;
+import com.android.services.telephony.common.Call;
+
import java.util.Set;
/**
@@ -31,35 +33,35 @@ import java.util.Set;
* are disconnected.
* Creates and manages the in-call state and provides a listener pattern for the presenters
* that want to listen in on the in-call state changes.
+ * TODO(klp): This class has become more of a state machine at this point. Consider renaming.
*/
public class InCallPresenter implements CallList.Listener {
private static InCallPresenter sInCallPresenter;
- private Context mContext;
+ private final StatusBarNotifier mStatusBarNotifier;
+ private final Set<InCallStateListener> mListeners = Sets.newHashSet();
+
private InCallState mInCallState = InCallState.HIDDEN;
private InCallActivity mInCallActivity;
- private final Set<InCallStateListener> mListeners = Sets.newHashSet();
- public static synchronized InCallPresenter getInstance() {
- if (sInCallPresenter == null) {
- sInCallPresenter = new InCallPresenter();
- }
+ public static InCallPresenter getInstance() {
+ Preconditions.checkNotNull(sInCallPresenter);
return sInCallPresenter;
}
- public void init(Context context) {
- Logger.i(this, "InCallPresenter initialized with context " + context);
- Preconditions.checkState(mContext == null);
-
- mContext = context;
- CallList.getInstance().addListener(this);
+ public static synchronized InCallPresenter init(Context context) {
+ Preconditions.checkState(sInCallPresenter == null);
+ sInCallPresenter = new InCallPresenter(context);
+ return sInCallPresenter;
}
public void setActivity(InCallActivity inCallActivity) {
mInCallActivity = inCallActivity;
mInCallState = InCallState.STARTED;
+ Logger.d(this, "UI Initialized");
+
// Since the UI just came up, imitate an update from the call list
// to set the proper UI state.
onCallListChange(CallList.getInstance());
@@ -75,21 +77,14 @@ public class InCallPresenter implements CallList.Listener {
public void onCallListChange(CallList callList) {
// fast fail if we are still starting up
if (mInCallState == InCallState.STARTING_UP) {
+ Logger.d(this, "Already on STARTING_UP, ignoring until ready");
return;
}
- InCallState newState = mInCallState;
- if (callList.getIncomingCall() != null) {
- newState = InCallState.INCOMING;
- } else if (callList.getActiveCall() != null) {
- newState = InCallState.INCALL;
- } else {
- newState = InCallState.HIDDEN;
- }
-
+ InCallState newState = getPotentialStateFromCallList(callList);
newState = startOrFinishUi(newState);
- // finally set the new state before announcing it to the world
+ // Set the new state before announcing it to the world
mInCallState = newState;
// notify listeners of new state
@@ -99,6 +94,22 @@ public class InCallPresenter implements CallList.Listener {
}
}
+ /**
+ * Given the call list, return the state in which the in-call screen should be.
+ */
+ public InCallState getPotentialStateFromCallList(CallList callList) {
+ InCallState newState = InCallState.HIDDEN;
+
+ if (callList.getIncomingCall() != null) {
+ newState = InCallState.INCOMING;
+ } else if (callList.getActiveCall() != null ||
+ callList.getBackgroundCall() != null) {
+ newState = InCallState.INCALL;
+ }
+
+ return newState;
+ }
+
public void addListener(InCallStateListener listener) {
Preconditions.checkNotNull(listener);
mListeners.add(listener);
@@ -115,26 +126,23 @@ public class InCallPresenter implements CallList.Listener {
* It returns a potential new middle state (STARTING_UP) if appropriate.
*/
private InCallState startOrFinishUi(InCallState newState) {
+ Logger.d(this, "startOrFInishUi: " + newState.toString());
+
// TODO(klp): Consider a proper state machine implementation
// if we need to show something, we need to start the Ui...
- if (newState != InCallState.HIDDEN) {
-
- // ...only if the UI is currently hidden
- if (mInCallState == InCallState.HIDDEN) {
- // TODO(klp): Update the flags to match the PhoneApp activity
- final Intent intent = new Intent(mContext, InCallActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
-
+ if (!newState.isHidden()) {
+
+ // 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;
}
- // (newState == InCallState.HIDDEN)
- // Else, we need to hide the UI...if it exists
} else if (mInCallActivity != null) {
- mListeners.clear();
-
// Null out reference before we start end sequence
InCallActivity temp = mInCallActivity;
mInCallActivity = null;
@@ -148,7 +156,12 @@ public class InCallPresenter implements CallList.Listener {
/**
* Private constructor. Must use getInstance() to get this singleton.
*/
- private InCallPresenter() {
+ private InCallPresenter(Context context) {
+ Preconditions.checkNotNull(context);
+
+ mStatusBarNotifier = new StatusBarNotifier(context);
+ addListener(mStatusBarNotifier);
+
CallList.getInstance().addListener(this);
}
@@ -156,12 +169,29 @@ public class InCallPresenter implements CallList.Listener {
* All the main states of InCallActivity.
*/
public enum InCallState {
+ // InCall Screen is off and there are no calls
HIDDEN,
+
+ // In call is in the process of starting up
STARTING_UP,
+
+ // In call has started but is not displaying any information
STARTED,
+
+ // Incoming-call screen is up
INCOMING,
- INCALL
- };
+
+ // In-call experience is showing
+ INCALL;
+
+ public boolean isIncoming() {
+ return (this == INCOMING);
+ }
+
+ public boolean isHidden() {
+ return (this == HIDDEN);
+ }
+ }
/**
* Interface implemented by classes that need to know about the InCall State.
diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
new file mode 100644
index 000000000..617be2fac
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.incallui;
+
+import com.google.common.base.Preconditions;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.incallui.InCallPresenter.InCallState;
+import com.android.services.telephony.common.Call;
+
+/**
+ * This class adds Notifications to the status bar for the in-call experience.
+ */
+public class StatusBarNotifier implements InCallPresenter.InCallStateListener {
+ // notification types
+ private static final int IN_CALL_NOTIFICATION = 1;
+
+ private final Context mContext;
+ private final NotificationManager mNotificationManager;
+
+ public StatusBarNotifier(Context context) {
+ Preconditions.checkNotNull(context);
+
+ mContext = context;
+ mNotificationManager =
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ /**
+ * Creates notifications according to the state we receive from {@link InCallPresenter}.
+ */
+ @Override
+ public void onStateChange(InCallState state, CallList callList) {
+
+ if (InCallState.STARTING_UP == state) {
+ // TODO: This method needs to move somewhere more appropriate for sharing
+ InCallState newState = InCallPresenter.getInstance()
+ .getPotentialStateFromCallList(callList);
+
+ updateNotificationAndLaunchIncomingCallUi(newState);
+ } else {
+ updateInCallNotification(state);
+ }
+ }
+
+ /**
+ * Updates the phone app's status bar notification based on the
+ * current telephony state, or cancels the notification if the phone
+ * is totally idle.
+ *
+ * This method will never actually launch the incoming-call UI.
+ * (Use updateNotificationAndLaunchIncomingCallUi() for that.)
+ */
+ private void updateInCallNotification(InCallState state) {
+ // allowFullScreenIntent=false means *don't* allow the incoming
+ // call UI to be launched.
+ updateInCallNotification(false, state);
+ }
+
+ /**
+ * Updates the phone app's status bar notification *and* launches the
+ * incoming call UI in response to a new incoming call.
+ *
+ * This is just like updateInCallNotification(), with one exception:
+ * If an incoming call is ringing (or call-waiting), the notification
+ * will also include a "fullScreenIntent" that will cause the
+ * InCallScreen to be launched immediately, unless the current
+ * foreground activity is marked as "immersive".
+ *
+ * (This is the mechanism that actually brings up the incoming call UI
+ * when we receive a "new ringing connection" event from the telephony
+ * layer.)
+ *
+ * Watch out: this method should ONLY be called directly from the code
+ * path in CallNotifier that handles the "new ringing connection"
+ * event from the telephony layer. All other places that update the
+ * in-call notification (like for phone state changes) should call
+ * updateInCallNotification() instead. (This ensures that we don't
+ * end up launching the InCallScreen multiple times for a single
+ * incoming call, which could cause slow responsiveness and/or visible
+ * glitches.)
+ *
+ * Also note that this method is safe to call even if the phone isn't
+ * actually ringing (or, more likely, if an incoming call *was*
+ * ringing briefly but then disconnected). In that case, we'll simply
+ * update or cancel the in-call notification based on the current
+ * phone state.
+ *
+ * @see #updateInCallNotification(boolean)
+ */
+ private void updateNotificationAndLaunchIncomingCallUi(InCallState state) {
+ // Set allowFullScreenIntent=true to indicate that we *should*
+ // launch the incoming call UI if necessary.
+ updateInCallNotification(true, state);
+ }
+
+
+ /**
+ * Take down the in-call notification.
+ * @see updateInCallNotification()
+ */
+ private void cancelInCall() {
+ Logger.d(this, "cancelInCall()...");
+ mNotificationManager.cancel(IN_CALL_NOTIFICATION);
+ }
+
+ /**
+ * Helper method for updateInCallNotification() and
+ * updateNotificationAndLaunchIncomingCallUi(): Update the phone app's
+ * status bar notification based on the current telephony state, or
+ * cancels the notification if the phone is totally idle.
+ *
+ * @param allowFullScreenIntent If true, *and* an incoming call is
+ * ringing, the notification will include a "fullScreenIntent"
+ * pointing at the InCallActivity (which will cause the InCallActivity
+ * to be launched.)
+ * Watch out: This should be set to true *only* when directly
+ * handling a new incoming call for the first time.
+ */
+ private void updateInCallNotification(boolean allowFullScreenIntent, InCallState state) {
+ int resId;
+ Logger.d(this, "updateInCallNotification(allowFullScreenIntent = "
+ + allowFullScreenIntent + ")...");
+
+ if (InCallState.INCALL != state && InCallState.INCOMING != state) {
+ cancelInCall();
+ return;
+ }
+
+ final PendingIntent inCallPendingIntent = getLaunchPendingIntent();
+ final Notification.Builder builder = getNotificationBuilder();
+
+ /*
+ * Set up the Intents that will get fires when the user interacts with the notificaiton.
+ */
+ builder.setContentIntent(inCallPendingIntent);
+ if (InCallState.INCOMING == state) {
+ if (allowFullScreenIntent) {
+ configureFullScreenIntent(builder, inCallPendingIntent);
+ }
+ } else if (InCallState.INCALL == state) {
+ addActiveCallIntents(builder);
+ }
+
+
+ /*
+ * Set up notification Ui.
+ */
+ setUpNotificationUi(builder);
+
+
+ /*
+ * Fire off the notification
+ */
+ Notification notification = builder.build();
+ Logger.d(this, "Notifying IN_CALL_NOTIFICATION: " + notification);
+ mNotificationManager.notify(IN_CALL_NOTIFICATION, notification);
+ }
+
+ /**
+ * Sets up the main Ui for the notification
+ */
+ private void setUpNotificationUi(Notification.Builder builder) {
+ // set the content
+ builder.setContentText(mContext.getString(R.string.notification_ongoing_call));
+ builder.setSmallIcon(R.drawable.stat_sys_phone_call);
+ }
+
+ private void addActiveCallIntents(Notification.Builder builder) {
+ Logger.i(this, "Will show \"hang-up\" action in the ongoing active call Notification");
+ // TODO: use better asset.
+ // TODO(klp): uncomment this for "hang-up" capability
+ //builder.addAction(R.drawable.stat_sys_phone_call_end,
+ // mContext.getText(R.string.notification_action_end_call),
+ // PhoneGlobals.createHangUpOngoingCallPendingIntent(mContext));
+ }
+
+ /**
+ * Adds fullscreen intent to the builder.
+ */
+ private void configureFullScreenIntent(Notification.Builder builder, PendingIntent intent) {
+ // Ok, we actually want to launch the incoming call
+ // UI at this point (in addition to simply posting a notification
+ // to the status bar). Setting fullScreenIntent will cause
+ // the InCallScreen to be launched immediately *unless* the
+ // current foreground activity is marked as "immersive".
+ Logger.d(this, "- Setting fullScreenIntent: " + intent);
+ builder.setFullScreenIntent(intent, true);
+
+ // Ugly hack alert:
+ //
+ // The NotificationManager has the (undocumented) behavior
+ // that it will *ignore* the fullScreenIntent field if you
+ // post a new Notification that matches the ID of one that's
+ // already active. Unfortunately this is exactly what happens
+ // when you get an incoming call-waiting call: the
+ // "ongoing call" notification is already visible, so the
+ // InCallScreen won't get launched in this case!
+ // (The result: if you bail out of the in-call UI while on a
+ // call and then get a call-waiting call, the incoming call UI
+ // won't come up automatically.)
+ //
+ // The workaround is to just notice this exact case (this is a
+ // call-waiting call *and* the InCallScreen is not in the
+ // foreground) and manually cancel the in-call notification
+ // before (re)posting it.
+ //
+ // TODO: there should be a cleaner way of avoiding this
+ // problem (see discussion in bug 3184149.)
+
+ // TODO(klp): reenable this for klp
+ /*if (incomingCall.getState() == Call.State.CALL_WAITING) {
+ Logger.i(this, "updateInCallNotification: call-waiting! force relaunch...");
+ // Cancel the IN_CALL_NOTIFICATION immediately before
+ // (re)posting it; this seems to force the
+ // NotificationManager to launch the fullScreenIntent.
+ mNotificationManager.cancel(IN_CALL_NOTIFICATION);
+ }*/
+ }
+
+ private Notification.Builder getNotificationBuilder() {
+ final Notification.Builder builder = new Notification.Builder(mContext);
+ builder.setOngoing(true);
+
+ // Make the notification prioritized over the other normal notifications.
+ builder.setPriority(Notification.PRIORITY_HIGH);
+
+ return builder;
+ }
+
+ private PendingIntent getLaunchPendingIntent() {
+
+ 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);
+
+ // PendingIntent that can be used to launch the InCallActivity. The
+ // system fires off this intent if the user pulls down the windowshade
+ // and clicks the notification's expanded view. It's also used to
+ // launch the InCallActivity immediately when when there's an incoming
+ // call (see the "fullScreenIntent" field below).
+ PendingIntent inCallPendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+
+ return inCallPendingIntent;
+ }
+}