1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/*
2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2013 The Android Open Source Project
3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License");
5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License.
6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at
7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *      http://www.apache.org/licenses/LICENSE-2.0
9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software
11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS,
12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and
14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License.
15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.incallui;
18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
199050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanianimport static android.telecom.Call.Details.PROPERTY_HIGH_DEF_AUDIO;
20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.contacts.common.compat.CallCompat.Details.PROPERTY_ENTERPRISE_CALL;
21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.incallui.NotificationBroadcastReceiver.ACTION_ACCEPT_VIDEO_UPGRADE_REQUEST;
22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.incallui.NotificationBroadcastReceiver.ACTION_ANSWER_VIDEO_INCOMING_CALL;
23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.incallui.NotificationBroadcastReceiver.ACTION_ANSWER_VOICE_INCOMING_CALL;
24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.incallui.NotificationBroadcastReceiver.ACTION_DECLINE_INCOMING_CALL;
25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.incallui.NotificationBroadcastReceiver.ACTION_DECLINE_VIDEO_UPGRADE_REQUEST;
26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport static com.android.incallui.NotificationBroadcastReceiver.ACTION_HANG_UP_ONGOING_CALL;
27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
28d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.Manifest;
29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.ActivityManager;
30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.Notification;
31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.NotificationManager;
32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.PendingIntent;
33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context;
34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Intent;
3583b20211c3be04a850de3674977deee8e448d17fEric Erfanianimport android.content.res.Resources;
36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.graphics.Bitmap;
37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.graphics.drawable.BitmapDrawable;
38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.graphics.drawable.Drawable;
39d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.graphics.drawable.Icon;
40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.media.AudioAttributes;
41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.net.Uri;
42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Build.VERSION;
43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Build.VERSION_CODES;
44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.ColorRes;
45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull;
46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.Nullable;
47d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.support.annotation.RequiresPermission;
48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.StringRes;
49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.VisibleForTesting;
50d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.support.v4.os.BuildCompat;
51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.Call.Details;
52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.PhoneAccount;
53d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.telecom.PhoneAccountHandle;
54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.TelecomManager;
55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.BidiFormatter;
56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.Spannable;
57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.SpannableString;
58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.TextDirectionHeuristics;
59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.TextUtils;
60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.style.ForegroundColorSpan;
61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.ContactsUtils;
62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.ContactsUtils.UserType;
63d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport com.android.contacts.common.lettertiles.LetterTileDrawable;
642f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.contacts.common.lettertiles.LetterTileDrawable.ContactType;
65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.preference.ContactsPreferences;
66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.util.BitmapUtil;
67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.util.ContactDisplayUtils;
68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil;
693128dea03a0e3981511dfed6f3ef555f0b574725twyenimport com.android.dialer.configprovider.ConfigProviderBindings;
70d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanianimport com.android.dialer.enrichedcall.EnrichedCallManager;
71d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanianimport com.android.dialer.enrichedcall.Session;
72d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanianimport com.android.dialer.multimedia.MultimediaData;
732f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.notification.NotificationChannelId;
749050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanianimport com.android.dialer.oem.MotorolaUtils;
75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.util.DrawableConverter;
76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.ContactInfoCache.ContactCacheEntry;
77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.InCallPresenter.InCallState;
79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.async.PausableExecutorImpl;
80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.CallList;
81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.DialerCall;
82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.DialerCallListener;
83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.ringtone.DialerRingtoneManager;
84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.ringtone.InCallTonePlayer;
85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.ringtone.ToneGeneratorFactory;
869050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanianimport com.android.incallui.videotech.utils.SessionModificationState;
87d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.util.List;
88d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.util.Locale;
89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Objects;
90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** This class adds Notifications to the status bar for the in-call experience. */
92d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanianpublic class StatusBarNotifier
93d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    implements InCallPresenter.InCallStateListener, EnrichedCallManager.StateChangedListener {
94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
952f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  private static final String NOTIFICATION_TAG = "STATUS_BAR_NOTIFIER";
962f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  private static final int NOTIFICATION_ID = 1;
972f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
98ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  // Notification types
99ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  // Indicates that no notification is currently showing.
100ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final int NOTIFICATION_NONE = 0;
101ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  // Notification for an active call. This is non-interruptive, but cannot be dismissed.
10210b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  private static final int NOTIFICATION_IN_CALL = 1;
103ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  // Notification for incoming calls. This is interruptive and will show up as a HUN.
10410b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  private static final int NOTIFICATION_INCOMING_CALL = 2;
10510b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  // Notification for incoming calls in the case where there is already an active call.
10610b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  // This is non-interruptive, but otherwise behaves the same as NOTIFICATION_INCOMING_CALL
10710b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  private static final int NOTIFICATION_INCOMING_CALL_QUIET = 3;
108ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final int PENDING_INTENT_REQUEST_CODE_NON_FULL_SCREEN = 0;
110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final int PENDING_INTENT_REQUEST_CODE_FULL_SCREEN = 1;
111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static final long[] VIBRATE_PATTERN = new long[] {0, 1000, 1000};
113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final Context mContext;
115ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final ContactInfoCache mContactInfoCache;
116ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final NotificationManager mNotificationManager;
117ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final DialerRingtoneManager mDialerRingtoneManager;
118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Nullable private ContactsPreferences mContactsPreferences;
119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int mCurrentNotification = NOTIFICATION_NONE;
120ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int mCallState = DialerCall.State.INVALID;
121ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int mSavedIcon = 0;
122ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private String mSavedContent = null;
123ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private Bitmap mSavedLargeIcon;
124ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private String mSavedContentTitle;
125ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private Uri mRingtone;
126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private StatusBarCallListener mStatusBarCallListener;
127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
128d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  public StatusBarNotifier(@NonNull Context context, @NonNull ContactInfoCache contactInfoCache) {
129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Objects.requireNonNull(context);
130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContext = context;
131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContactsPreferences = ContactsPreferencesFactory.newContactsPreferences(mContext);
132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContactInfoCache = contactInfoCache;
133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mNotificationManager = context.getSystemService(NotificationManager.class);
134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mDialerRingtoneManager =
135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new DialerRingtoneManager(
136ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            new InCallTonePlayer(new ToneGeneratorFactory(), new PausableExecutorImpl()),
137ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            CallList.getInstance());
138ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mCurrentNotification = NOTIFICATION_NONE;
139ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
140ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
141ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
142ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Should only be called from a irrecoverable state where it is necessary to dismiss all
143ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * notifications.
144ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
145ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  static void clearAllCallNotifications(Context backupContext) {
146d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.i(
147d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.clearAllCallNotifications",
148d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "something terrible happened, clear all InCall notifications");
149ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
150ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    NotificationManager notificationManager =
151ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        backupContext.getSystemService(NotificationManager.class);
1522f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    notificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
153ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
154ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
155ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static int getWorkStringFromPersonalString(int resId) {
156ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (resId == R.string.notification_ongoing_call) {
157ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return R.string.notification_ongoing_work_call;
158ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (resId == R.string.notification_ongoing_call_wifi) {
159ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return R.string.notification_ongoing_work_call_wifi;
160ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (resId == R.string.notification_incoming_call_wifi) {
161ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return R.string.notification_incoming_work_call_wifi;
162ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (resId == R.string.notification_incoming_call) {
163ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return R.string.notification_incoming_work_call;
164ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
165ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return resId;
166ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
167ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
168ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
169ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
170ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Returns PendingIntent for answering a phone call. This will typically be used from Notification
171ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * context.
172ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
173ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static PendingIntent createNotificationPendingIntent(Context context, String action) {
174ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final Intent intent = new Intent(action, null, context, NotificationBroadcastReceiver.class);
175ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return PendingIntent.getBroadcast(context, 0, intent, 0);
176ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
177ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
178ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Creates notifications according to the state we receive from {@link InCallPresenter}. */
179ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
180d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
181ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
182d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.d("StatusBarNotifier.onStateChange", "%s->%s", oldState, newState);
183ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    updateNotification(callList);
184ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
185ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
186d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  @Override
187d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  public void onEnrichedCallStateChanged() {
188d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    LogUtil.enterBlock("StatusBarNotifier.onEnrichedCallStateChanged");
189d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    updateNotification(CallList.getInstance());
190d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  }
191d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian
192ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
193ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Updates the phone app's status bar notification *and* launches the incoming call UI in response
194ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * to a new incoming call.
195ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
196ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * <p>If an incoming call is ringing (or call-waiting), the notification will also include a
197ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * "fullScreenIntent" that will cause the InCallScreen to be launched, unless the current
198ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * foreground activity is marked as "immersive".
199ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
200ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * <p>(This is the mechanism that actually brings up the incoming call UI when we receive a "new
201ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * ringing connection" event from the telephony layer.)
202ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
203ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * <p>Also note that this method is safe to call even if the phone isn't actually ringing (or,
204ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * more likely, if an incoming call *was* ringing briefly but then disconnected). In that case,
205ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * we'll simply update or cancel the in-call notification based on the current phone state.
206ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
207ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @see #updateInCallNotification(CallList)
208ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
209d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
210d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  public void updateNotification(CallList callList) {
211ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    updateInCallNotification(callList);
212ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
213ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
214ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
215ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Take down the in-call notification.
216ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
217ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @see #updateInCallNotification(CallList)
218ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
219ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void cancelNotification() {
220ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mStatusBarCallListener != null) {
221ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      setStatusBarCallListener(null);
222ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
223ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mCurrentNotification != NOTIFICATION_NONE) {
2248369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian      LogUtil.i("StatusBarNotifier.cancelNotification", "cancel");
2252f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
226ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
227ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mCurrentNotification = NOTIFICATION_NONE;
228ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
229ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
230ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
231ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Helper method for updateInCallNotification() and updateNotification(): Update the phone app's
232ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * status bar notification based on the current telephony state, or cancels the notification if
233ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * the phone is totally idle.
234ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
235d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
236ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void updateInCallNotification(CallList callList) {
237d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.d("StatusBarNotifier.updateInCallNotification", "");
238ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
239ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final DialerCall call = getCallToShow(callList);
240ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
241ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call != null) {
242ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      showNotification(callList, call);
243ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
244ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      cancelNotification();
245ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
246ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
247ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
248d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
249ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void showNotification(final CallList callList, final DialerCall call) {
250ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final boolean isIncoming =
251ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (call.getState() == DialerCall.State.INCOMING
252ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            || call.getState() == DialerCall.State.CALL_WAITING);
253ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    setStatusBarCallListener(new StatusBarCallListener(call));
254ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
255ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // we make a call to the contact info cache to query for supplemental data to what the
256ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // call provides.  This includes the contact name and photo.
257ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // This callback will always get called immediately and synchronously with whatever data
258ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // it has available, and may make a subsequent call later (same thread) if it had to
259ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // call into the contacts provider for more data.
260ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContactInfoCache.findInfo(
261ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        call,
262ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        isIncoming,
263ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new ContactInfoCacheCallback() {
264ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          @Override
265d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
266ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
267ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            DialerCall call = callList.getCallById(callId);
268ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            if (call != null) {
269ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              call.getLogState().contactLookupResult = entry.contactLookupResult;
270ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              buildAndSendNotification(callList, call, entry);
271ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            }
272ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          }
273ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
274ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          @Override
275d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
276ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          public void onImageLoadComplete(String callId, ContactCacheEntry entry) {
277ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            DialerCall call = callList.getCallById(callId);
278ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            if (call != null) {
279ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              buildAndSendNotification(callList, call, entry);
280ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            }
281ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          }
282ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        });
283ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
284ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
285ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Sets up the main Ui for the notification */
286d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
287ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void buildAndSendNotification(
288ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      CallList callList, DialerCall originalCall, ContactCacheEntry contactInfo) {
289ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // This can get called to update an existing notification after contact information has come
290ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // back. However, it can happen much later. Before we continue, we need to make sure that
291ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // the call being passed in is still the one we want to show in the notification.
292ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final DialerCall call = getCallToShow(callList);
293ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call == null || !call.getId().equals(originalCall.getId())) {
294ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return;
295ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
296ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
297ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int callState = call.getState();
298ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
299ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Check if data has changed; if nothing is different, don't issue another notification.
300ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int iconResId = getIconToDisplay(call);
30183b20211c3be04a850de3674977deee8e448d17fEric Erfanian    Bitmap largeIcon = getLargeIconToDisplay(mContext, contactInfo, call);
302ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final String content = getContentString(call, contactInfo.userType);
303ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final String contentTitle = getContentTitle(contactInfo, call);
304ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
305ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final boolean isVideoUpgradeRequest =
306d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        call.getVideoTech().getSessionModificationState()
3079050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian            == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST;
308ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int notificationType;
309ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (callState == DialerCall.State.INCOMING
310ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || callState == DialerCall.State.CALL_WAITING
311ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || isVideoUpgradeRequest) {
3123128dea03a0e3981511dfed6f3ef555f0b574725twyen      if (ConfigProviderBindings.get(mContext)
3133128dea03a0e3981511dfed6f3ef555f0b574725twyen          .getBoolean("quiet_incoming_call_if_ui_showing", true)) {
3143128dea03a0e3981511dfed6f3ef555f0b574725twyen        notificationType =
3153128dea03a0e3981511dfed6f3ef555f0b574725twyen            InCallPresenter.getInstance().isShowingInCallUi()
3163128dea03a0e3981511dfed6f3ef555f0b574725twyen                ? NOTIFICATION_INCOMING_CALL_QUIET
3173128dea03a0e3981511dfed6f3ef555f0b574725twyen                : NOTIFICATION_INCOMING_CALL;
3183128dea03a0e3981511dfed6f3ef555f0b574725twyen      } else {
3193128dea03a0e3981511dfed6f3ef555f0b574725twyen        boolean alreadyActive =
3203128dea03a0e3981511dfed6f3ef555f0b574725twyen            callList.getActiveOrBackgroundCall() != null
3213128dea03a0e3981511dfed6f3ef555f0b574725twyen                && InCallPresenter.getInstance().isShowingInCallUi();
3223128dea03a0e3981511dfed6f3ef555f0b574725twyen        notificationType =
3233128dea03a0e3981511dfed6f3ef555f0b574725twyen            alreadyActive ? NOTIFICATION_INCOMING_CALL_QUIET : NOTIFICATION_INCOMING_CALL;
3243128dea03a0e3981511dfed6f3ef555f0b574725twyen      }
325ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
326ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      notificationType = NOTIFICATION_IN_CALL;
327ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
328ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
329ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (!checkForChangeAndSaveData(
330ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        iconResId,
331ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        content,
332ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        largeIcon,
333ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        contentTitle,
334ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        callState,
335ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        notificationType,
3368369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian        contactInfo.contactRingtoneUri)) {
337ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return;
338ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
339ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
340ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (largeIcon != null) {
341ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      largeIcon = getRoundedIcon(largeIcon);
342ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
343ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
344ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // This builder is used for the notification shown when the device is locked and the user
345ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // has set their notification settings to 'hide sensitive content'
346ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // {@see Notification.Builder#setPublicVersion}.
347ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Notification.Builder publicBuilder = new Notification.Builder(mContext);
348ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    publicBuilder
349ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        .setSmallIcon(iconResId)
350d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        .setColor(mContext.getResources().getColor(R.color.dialer_theme_color, mContext.getTheme()))
351ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        // Hide work call state for the lock screen notification
352ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        .setContentTitle(getContentString(call, ContactsUtils.USER_TYPE_CURRENT));
353ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    setNotificationWhen(call, callState, publicBuilder);
354ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
355ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Builder for the notification shown when the device is unlocked or the user has set their
356ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // notification settings to 'show all notification content'.
357ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final Notification.Builder builder = getNotificationBuilder();
358ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setPublicVersion(publicBuilder.build());
359ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
360ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Set up the main intent to send the user to the in-call screen
361d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    builder.setContentIntent(createLaunchPendingIntent(false /* isFullScreen */));
362ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
363ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Set the intent as a full screen intent as well if a call is incoming
364d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    PhoneAccountHandle accountHandle = call.getAccountHandle();
365d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (accountHandle == null) {
366d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      accountHandle = getAnyPhoneAccount();
367d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
36810b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian
36910b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian    LogUtil.i("StatusBarNotifier.buildAndSendNotification", "notificationType=" + notificationType);
37010b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian    switch (notificationType) {
37110b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian      case NOTIFICATION_INCOMING_CALL:
3722f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        if (BuildCompat.isAtLeastO()) {
3732f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          builder.setChannelId(NotificationChannelId.INCOMING_CALL);
3742f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        }
37510b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        configureFullScreenIntent(builder, createLaunchPendingIntent(true /* isFullScreen */));
37610b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        // Set the notification category and bump the priority for incoming calls
37710b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        builder.setCategory(Notification.CATEGORY_CALL);
37810b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        // This will be ignored on O+ and handled by the channel
37910b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        builder.setPriority(Notification.PRIORITY_MAX);
38010b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        if (mCurrentNotification != NOTIFICATION_INCOMING_CALL) {
38110b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian          LogUtil.i(
38210b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian              "StatusBarNotifier.buildAndSendNotification",
38310b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian              "Canceling old notification so this one can be noisy");
38410b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian          // Moving from a non-interuptive notification (or none) to a noisy one. Cancel the old
38510b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian          // notification (if there is one) so the fullScreenIntent or HUN will show
3862f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
38710b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        }
38810b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        break;
38910b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian      case NOTIFICATION_INCOMING_CALL_QUIET:
3902f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        if (BuildCompat.isAtLeastO()) {
3912f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          builder.setChannelId(NotificationChannelId.ONGOING_CALL);
3922f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        }
39310b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        break;
39410b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian      case NOTIFICATION_IN_CALL:
3952f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        if (BuildCompat.isAtLeastO()) {
3962f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          publicBuilder.setColorized(true);
3972f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          builder.setColorized(true);
3982f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          builder.setChannelId(NotificationChannelId.ONGOING_CALL);
3992f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        }
40010b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        break;
401ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
402ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
403ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Set the content
404ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setContentText(content);
405ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setSmallIcon(iconResId);
406ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setContentTitle(contentTitle);
407ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setLargeIcon(largeIcon);
408d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    builder.setColor(
409d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        mContext.getResources().getColor(R.color.dialer_theme_color, mContext.getTheme()));
410ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
411ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (isVideoUpgradeRequest) {
412ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.setUsesChronometer(false);
413ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      addDismissUpgradeRequestAction(builder);
414ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      addAcceptUpgradeRequestAction(builder);
415ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
416ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      createIncomingCallNotification(call, callState, builder);
417ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
418ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
419ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    addPersonReference(builder, contactInfo, call);
420ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
421ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Fire off the notification
422ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Notification notification = builder.build();
423ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
424ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mDialerRingtoneManager.shouldPlayRingtone(callState, contactInfo.contactRingtoneUri)) {
425ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      notification.flags |= Notification.FLAG_INSISTENT;
426ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      notification.sound = contactInfo.contactRingtoneUri;
427ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      AudioAttributes.Builder audioAttributes = new AudioAttributes.Builder();
428ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      audioAttributes.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC);
429ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      audioAttributes.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
430ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      notification.audioAttributes = audioAttributes.build();
431ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (mDialerRingtoneManager.shouldVibrate(mContext.getContentResolver())) {
432ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        notification.vibrate = VIBRATE_PATTERN;
433ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
434ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
435ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mDialerRingtoneManager.shouldPlayCallWaitingTone(callState)) {
436d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      LogUtil.v("StatusBarNotifier.buildAndSendNotification", "playing call waiting tone");
437ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mDialerRingtoneManager.playCallWaitingTone();
438ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
439ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
440d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.i(
441d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.buildAndSendNotification",
442d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "displaying notification for " + notificationType);
443d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
444ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    try {
4452f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification);
446ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } catch (RuntimeException e) {
447ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // TODO(b/34744003): Move the memory stats into silent feedback PSD.
448ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
449ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
450ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      activityManager.getMemoryInfo(memoryInfo);
451ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      throw new RuntimeException(
452ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          String.format(
453d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian              Locale.US,
454ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              "Error displaying notification with photo type: %d (low memory? %b, availMem: %d)",
455d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian              contactInfo.photoType,
456d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian              memoryInfo.lowMemory,
457d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian              memoryInfo.availMem),
458ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          e);
459ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
460ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    call.getLatencyReport().onNotificationShown();
461ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mCurrentNotification = notificationType;
462ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
463ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
464d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @Nullable
465d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
466d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private PhoneAccountHandle getAnyPhoneAccount() {
467d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    PhoneAccountHandle accountHandle;
468d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
469d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    accountHandle = telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
470d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (accountHandle == null) {
471d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      List<PhoneAccountHandle> accountHandles = telecomManager.getCallCapablePhoneAccounts();
472d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (!accountHandles.isEmpty()) {
473d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        accountHandle = accountHandles.get(0);
474d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      }
475d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
476d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    return accountHandle;
477d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
478d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
479ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void createIncomingCallNotification(
480ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      DialerCall call, int state, Notification.Builder builder) {
481ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    setNotificationWhen(call, state, builder);
482ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
483ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Add hang up option for any active calls (active | onhold), outgoing calls (dialing).
484ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (state == DialerCall.State.ACTIVE
485ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || state == DialerCall.State.ONHOLD
486ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || DialerCall.State.isDialing(state)) {
487ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      addHangupAction(builder);
488ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (state == DialerCall.State.INCOMING || state == DialerCall.State.CALL_WAITING) {
489ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      addDismissAction(builder);
490ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (call.isVideoCall()) {
491ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        addVideoCallAction(builder);
492ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      } else {
493ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        addAnswerAction(builder);
494ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
495ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
496ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
497ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
498ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
499ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Sets the notification's when section as needed. For active calls, this is explicitly set as the
500ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * duration of the call. For all other states, the notification will automatically show the time
501ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * at which the notification was created.
502ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
503ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void setNotificationWhen(DialerCall call, int state, Notification.Builder builder) {
504ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (state == DialerCall.State.ACTIVE) {
505ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.setUsesChronometer(true);
506ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.setWhen(call.getConnectTimeMillis());
507ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
508ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.setUsesChronometer(false);
509ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
510ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
511ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
512ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
513ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Checks the new notification data and compares it against any notification that we are already
514ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * displaying. If the data is exactly the same, we return false so that we do not issue a new
515ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * notification for the exact same data.
516ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
517ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private boolean checkForChangeAndSaveData(
518ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      int icon,
519ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      String content,
520ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Bitmap largeIcon,
521ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      String contentTitle,
522ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      int state,
523ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      int notificationType,
5248369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian      Uri ringtone) {
525ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
526ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // The two are different:
527ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // if new title is not null, it should be different from saved version OR
528ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // if new title is null, the saved version should not be null
529ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final boolean contentTitleChanged =
530ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (contentTitle != null && !contentTitle.equals(mSavedContentTitle))
531ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            || (contentTitle == null && mSavedContentTitle != null);
532ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
5338369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian    boolean largeIconChanged =
5348369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian        mSavedLargeIcon == null ? largeIcon != null : !mSavedLargeIcon.sameAs(largeIcon);
5358369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian
536ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // any change means we are definitely updating
537ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    boolean retval =
538ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (mSavedIcon != icon)
539ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            || !Objects.equals(mSavedContent, content)
540ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            || (mCallState != state)
5418369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian            || largeIconChanged
542ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            || contentTitleChanged
5438369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian            || !Objects.equals(mRingtone, ringtone);
544ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
545ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // If we aren't showing a notification right now or the notification type is changing,
546ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // definitely do an update.
547ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mCurrentNotification != notificationType) {
548ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (mCurrentNotification == NOTIFICATION_NONE) {
549d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        LogUtil.d(
550d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            "StatusBarNotifier.checkForChangeAndSaveData", "showing notification for first time.");
551ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
552ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      retval = true;
553ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
554ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
555ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mSavedIcon = icon;
556ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mSavedContent = content;
557ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mCallState = state;
558ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mSavedLargeIcon = largeIcon;
559ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mSavedContentTitle = contentTitle;
560ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mRingtone = ringtone;
561ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
562ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (retval) {
563d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      LogUtil.d(
564d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          "StatusBarNotifier.checkForChangeAndSaveData", "data changed.  Showing notification");
565ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
566ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
567ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return retval;
568ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
569ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
570ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Returns the main string to use in the notification. */
571ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @VisibleForTesting
572ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Nullable
573ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  String getContentTitle(ContactCacheEntry contactInfo, DialerCall call) {
5742f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (call.isConferenceCall()) {
5752f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      return CallerInfoUtils.getConferenceString(
5762f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          mContext, call.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE));
577ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
578ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
579ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    String preferredName =
580ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        ContactDisplayUtils.getPreferredDisplayName(
581ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            contactInfo.namePrimary, contactInfo.nameAlternative, mContactsPreferences);
582ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (TextUtils.isEmpty(preferredName)) {
583ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return TextUtils.isEmpty(contactInfo.number)
584ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          ? null
585ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          : BidiFormatter.getInstance()
586ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              .unicodeWrap(contactInfo.number, TextDirectionHeuristics.LTR);
587ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
588ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return preferredName;
589ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
590ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
591ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addPersonReference(
592ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Notification.Builder builder, ContactCacheEntry contactInfo, DialerCall call) {
593ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Query {@link Contacts#CONTENT_LOOKUP_URI} directly with work lookup key is not allowed.
594ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // So, do not pass {@link Contacts#CONTENT_LOOKUP_URI} to NotificationManager to avoid
595ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // NotificationManager using it.
596ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (contactInfo.lookupUri != null && contactInfo.userType != ContactsUtils.USER_TYPE_WORK) {
597ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.addPerson(contactInfo.lookupUri.toString());
598ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (!TextUtils.isEmpty(call.getNumber())) {
599ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.addPerson(Uri.fromParts(PhoneAccount.SCHEME_TEL, call.getNumber(), null).toString());
600ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
601ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
602ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
603ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Gets a large icon from the contact info object to display in the notification. */
60483b20211c3be04a850de3674977deee8e448d17fEric Erfanian  private static Bitmap getLargeIconToDisplay(
60583b20211c3be04a850de3674977deee8e448d17fEric Erfanian      Context context, ContactCacheEntry contactInfo, DialerCall call) {
60683b20211c3be04a850de3674977deee8e448d17fEric Erfanian    Resources resources = context.getResources();
607ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Bitmap largeIcon = null;
608ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (contactInfo.photo != null && (contactInfo.photo instanceof BitmapDrawable)) {
609ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      largeIcon = ((BitmapDrawable) contactInfo.photo).getBitmap();
610ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
611d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (contactInfo.photo == null) {
61283b20211c3be04a850de3674977deee8e448d17fEric Erfanian      int width = (int) resources.getDimension(android.R.dimen.notification_large_icon_width);
61383b20211c3be04a850de3674977deee8e448d17fEric Erfanian      int height = (int) resources.getDimension(android.R.dimen.notification_large_icon_height);
6142f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      @ContactType
6152f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      int contactType =
6162f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian          LetterTileDrawable.getContactTypeFromPrimitives(
6172f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              CallerInfoUtils.isVoiceMailNumber(context, call),
6182f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              call.isSpam(),
6192f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              contactInfo.isBusiness,
6202f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              call.getNumberPresentation(),
6212f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian              call.isConferenceCall() && !call.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE));
62283b20211c3be04a850de3674977deee8e448d17fEric Erfanian      LetterTileDrawable lettertile = new LetterTileDrawable(resources);
623d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
624d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      lettertile.setCanonicalDialerLetterTileDetails(
625d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          contactInfo.namePrimary == null ? contactInfo.number : contactInfo.namePrimary,
626d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          contactInfo.lookupKey,
627d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          LetterTileDrawable.SHAPE_CIRCLE,
628d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          contactType);
629d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      largeIcon = lettertile.getBitmap(width, height);
630d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
631d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
632ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call.isSpam()) {
63383b20211c3be04a850de3674977deee8e448d17fEric Erfanian      Drawable drawable = resources.getDrawable(R.drawable.blocked_contact, context.getTheme());
634ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      largeIcon = DrawableConverter.drawableToBitmap(drawable);
635ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
636ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return largeIcon;
637ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
638ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
639ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private Bitmap getRoundedIcon(Bitmap bitmap) {
640ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (bitmap == null) {
641ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return null;
642ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
643ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int height =
644ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (int) mContext.getResources().getDimension(android.R.dimen.notification_large_icon_height);
645ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int width =
646ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (int) mContext.getResources().getDimension(android.R.dimen.notification_large_icon_width);
647ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return BitmapUtil.getRoundedBitmap(bitmap, width, height);
648ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
649ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
650ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
651ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Returns the appropriate icon res Id to display based on the call for which we want to display
652ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * information.
653ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
654ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int getIconToDisplay(DialerCall call) {
655ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Even if both lines are in use, we only show a single item in
656ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // the expanded Notifications UI.  It's labeled "Ongoing call"
657ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // (or "On hold" if there's only one call, and it's on hold.)
658ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Also, we don't have room to display caller-id info from two
659ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // different calls.  So if both lines are in use, display info
660ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // from the foreground call.  And if there's a ringing call,
661ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // display that regardless of the state of the other calls.
662ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call.getState() == DialerCall.State.ONHOLD) {
663ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return R.drawable.ic_phone_paused_white_24dp;
664d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (call.getVideoTech().getSessionModificationState()
6659050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
666d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      return R.drawable.quantum_ic_videocam_white_24;
6679050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian    } else if (call.hasProperty(PROPERTY_HIGH_DEF_AUDIO)
6689050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        && MotorolaUtils.shouldShowHdIconInNotification(mContext)) {
6692f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      // Normally when a call is ongoing the status bar displays an icon of a phone. This is a
6702f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      // helpful hint for users so they know how to get back to the call. For Sprint HD calls, we
6712f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      // replace this icon with an icon of a phone with a HD badge. This is a carrier requirement.
6729050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian      return R.drawable.ic_hd_call;
673ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
6742f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    // If ReturnToCall is enabled, use the static icon. The animated one will show in the bubble.
6752f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (ReturnToCallController.isEnabled(mContext)) {
6762f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      return R.drawable.quantum_ic_call_white_24;
6772f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    } else {
6782f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      return R.drawable.on_going_call;
6792f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    }
680ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
681ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
682ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Returns the message to use with the notification. */
683ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private String getContentString(DialerCall call, @UserType long userType) {
684ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    boolean isIncomingOrWaiting =
685ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        call.getState() == DialerCall.State.INCOMING
686ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            || call.getState() == DialerCall.State.CALL_WAITING;
687ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
688ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (isIncomingOrWaiting
689ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        && call.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED) {
690ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
691ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (!TextUtils.isEmpty(call.getChildNumber())) {
692ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        return mContext.getString(R.string.child_number, call.getChildNumber());
693ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      } else if (!TextUtils.isEmpty(call.getCallSubject()) && call.isCallSubjectSupported()) {
694ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        return call.getCallSubject();
695ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
696ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
697ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
698ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    int resId = R.string.notification_ongoing_call;
699ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call.hasProperty(Details.PROPERTY_WIFI)) {
700ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      resId = R.string.notification_ongoing_call_wifi;
701ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
702ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
703ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (isIncomingOrWaiting) {
704d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      if (call.isSpam()) {
705d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        resId = R.string.notification_incoming_spam_call;
7062f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      } else if (shouldShowEnrichedCallNotification(call.getEnrichedCallSession())) {
7072f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        resId = getECIncomingCallText(call.getEnrichedCallSession());
708d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      } else if (call.hasProperty(Details.PROPERTY_WIFI)) {
709ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        resId = R.string.notification_incoming_call_wifi;
710ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      } else {
711d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        resId = R.string.notification_incoming_call;
712ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
713ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (call.getState() == DialerCall.State.ONHOLD) {
714ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      resId = R.string.notification_on_hold;
715ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (DialerCall.State.isDialing(call.getState())) {
716ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      resId = R.string.notification_dialing;
717d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (call.getVideoTech().getSessionModificationState()
7189050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
719ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      resId = R.string.notification_requesting_video_call;
720ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
721ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
722ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Is the call placed through work connection service.
723ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    boolean isWorkCall = call.hasProperty(PROPERTY_ENTERPRISE_CALL);
724ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (userType == ContactsUtils.USER_TYPE_WORK || isWorkCall) {
725ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      resId = getWorkStringFromPersonalString(resId);
726ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
727ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
728ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return mContext.getString(resId);
729ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
730ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
7312f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  private boolean shouldShowEnrichedCallNotification(Session session) {
7322f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    if (session == null) {
7332f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      return false;
7342f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    }
7352f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    return session.getMultimediaData().hasData() || session.getMultimediaData().isImportant();
7362f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian  }
7372f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
738d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  private int getECIncomingCallText(Session session) {
739d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    int resId;
740d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    MultimediaData data = session.getMultimediaData();
741d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    boolean hasImage = data.hasImageData();
742d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    boolean hasSubject = !TextUtils.isEmpty(data.getText());
743d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    boolean hasMap = data.getLocation() != null;
744d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    if (data.isImportant()) {
745d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      if (hasMap) {
746d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        if (hasImage) {
747d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          if (hasSubject) {
748d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian            resId = R.string.important_notification_incoming_call_with_photo_message_location;
749d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          } else {
750d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian            resId = R.string.important_notification_incoming_call_with_photo_location;
751d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          }
752d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        } else if (hasSubject) {
753d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.important_notification_incoming_call_with_message_location;
754d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        } else {
755d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.important_notification_incoming_call_with_location;
756d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        }
757d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      } else if (hasImage) {
758d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        if (hasSubject) {
759d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.important_notification_incoming_call_with_photo_message;
760d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        } else {
761d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.important_notification_incoming_call_with_photo;
762d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        }
7632f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      } else if (hasSubject) {
764cded3beaf28a703e1ef8f71bbc6836e6806c3736Tobias Thierer        resId = R.string.important_notification_incoming_call_with_message;
7652f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian      } else {
7662f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian        resId = R.string.important_notification_incoming_call;
767d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      }
768d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      if (mContext.getString(resId).length() > 50) {
769d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        resId = R.string.important_notification_incoming_call_attachments;
770d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      }
771d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    } else {
772d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      if (hasMap) {
773d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        if (hasImage) {
774d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          if (hasSubject) {
775d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian            resId = R.string.notification_incoming_call_with_photo_message_location;
776d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          } else {
777d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian            resId = R.string.notification_incoming_call_with_photo_location;
778d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          }
779d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        } else if (hasSubject) {
780d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.notification_incoming_call_with_message_location;
781d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        } else {
782d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.notification_incoming_call_with_location;
783d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        }
784d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      } else if (hasImage) {
785d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        if (hasSubject) {
786d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.notification_incoming_call_with_photo_message;
787d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        } else {
788d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian          resId = R.string.notification_incoming_call_with_photo;
789d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        }
790d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      } else {
791d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        resId = R.string.notification_incoming_call_with_message;
792d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      }
793d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    }
794d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    if (mContext.getString(resId).length() > 50) {
795d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      resId = R.string.notification_incoming_call_attachments;
796d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    }
797d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    return resId;
798d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  }
799d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian
800ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Gets the most relevant call to display in the notification. */
801ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private DialerCall getCallToShow(CallList callList) {
802ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (callList == null) {
803ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return null;
804ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
805ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    DialerCall call = callList.getIncomingCall();
806ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call == null) {
807ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      call = callList.getOutgoingCall();
808ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
809ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call == null) {
810ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      call = callList.getVideoUpgradeRequestCall();
811ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
812ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call == null) {
813ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      call = callList.getActiveOrBackgroundCall();
814ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
815ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return call;
816ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
817ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
818ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private Spannable getActionText(@StringRes int stringRes, @ColorRes int colorRes) {
819ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Spannable spannable = new SpannableString(mContext.getText(stringRes));
820ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) {
821ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // This will only work for cases where the Notification.Builder has a fullscreen intent set
822ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Notification.Builder that does not have a full screen intent will take the color of the
823ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // app and the following leads to a no-op.
824ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      spannable.setSpan(
825ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          new ForegroundColorSpan(mContext.getColor(colorRes)), 0, spannable.length(), 0);
826ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
827ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return spannable;
828ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
829ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
830ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addAnswerAction(Notification.Builder builder) {
831d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.d(
832d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.addAnswerAction",
833d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "will show \"answer\" action in the incoming call Notification");
834ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    PendingIntent answerVoicePendingIntent =
835ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        createNotificationPendingIntent(mContext, ACTION_ANSWER_VOICE_INCOMING_CALL);
836ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addAction(
837d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        new Notification.Action.Builder(
8382f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian                Icon.createWithResource(mContext, R.drawable.quantum_ic_call_white_24),
839d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                getActionText(
840d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                    R.string.notification_action_answer, R.color.notification_action_accept),
841d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                answerVoicePendingIntent)
842d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            .build());
843ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
844ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
845ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addDismissAction(Notification.Builder builder) {
846d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.d(
847d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.addDismissAction",
848d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "will show \"decline\" action in the incoming call Notification");
849ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    PendingIntent declinePendingIntent =
850ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        createNotificationPendingIntent(mContext, ACTION_DECLINE_INCOMING_CALL);
851ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addAction(
852d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        new Notification.Action.Builder(
853d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian                Icon.createWithResource(mContext, R.drawable.quantum_ic_close_white_24),
854d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                getActionText(
855d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                    R.string.notification_action_dismiss, R.color.notification_action_dismiss),
856d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                declinePendingIntent)
857d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            .build());
858ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
859ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
860ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addHangupAction(Notification.Builder builder) {
861d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.d(
862d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.addHangupAction",
863d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "will show \"hang-up\" action in the ongoing active call Notification");
864ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    PendingIntent hangupPendingIntent =
865ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        createNotificationPendingIntent(mContext, ACTION_HANG_UP_ONGOING_CALL);
866ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addAction(
867d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        new Notification.Action.Builder(
868d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                Icon.createWithResource(mContext, R.drawable.ic_call_end_white_24dp),
86910b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian                mContext.getText(R.string.notification_action_end_call),
870d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                hangupPendingIntent)
871d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            .build());
872ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
873ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
874ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addVideoCallAction(Notification.Builder builder) {
875d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.i(
876d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.addVideoCallAction",
877d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "will show \"video\" action in the incoming call Notification");
878ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    PendingIntent answerVideoPendingIntent =
879ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        createNotificationPendingIntent(mContext, ACTION_ANSWER_VIDEO_INCOMING_CALL);
880ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addAction(
881d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        new Notification.Action.Builder(
882d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian                Icon.createWithResource(mContext, R.drawable.quantum_ic_videocam_white_24),
883d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                getActionText(
884d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                    R.string.notification_action_answer_video,
885d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                    R.color.notification_action_answer_video),
886d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                answerVideoPendingIntent)
887d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            .build());
888ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
889ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
890ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addAcceptUpgradeRequestAction(Notification.Builder builder) {
891d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.i(
892d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.addAcceptUpgradeRequestAction",
893d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "will show \"accept upgrade\" action in the incoming call Notification");
894ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    PendingIntent acceptVideoPendingIntent =
895ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        createNotificationPendingIntent(mContext, ACTION_ACCEPT_VIDEO_UPGRADE_REQUEST);
896ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addAction(
897d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        new Notification.Action.Builder(
898d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian                Icon.createWithResource(mContext, R.drawable.quantum_ic_videocam_white_24),
899d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                getActionText(
900d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                    R.string.notification_action_accept, R.color.notification_action_accept),
901d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                acceptVideoPendingIntent)
902d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            .build());
903ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
904ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
905ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void addDismissUpgradeRequestAction(Notification.Builder builder) {
906d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.i(
907d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "StatusBarNotifier.addDismissUpgradeRequestAction",
908d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        "will show \"dismiss upgrade\" action in the incoming call Notification");
909ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    PendingIntent declineVideoPendingIntent =
910ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        createNotificationPendingIntent(mContext, ACTION_DECLINE_VIDEO_UPGRADE_REQUEST);
911ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addAction(
912d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        new Notification.Action.Builder(
913d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian                Icon.createWithResource(mContext, R.drawable.quantum_ic_videocam_white_24),
914d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                getActionText(
915d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                    R.string.notification_action_dismiss, R.color.notification_action_dismiss),
916d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian                declineVideoPendingIntent)
917d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            .build());
918ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
919ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
920ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Adds fullscreen intent to the builder. */
92110b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  private void configureFullScreenIntent(Notification.Builder builder, PendingIntent intent) {
922ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Ok, we actually want to launch the incoming call
923ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // UI at this point (in addition to simply posting a notification
924ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // to the status bar).  Setting fullScreenIntent will cause
925ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // the InCallScreen to be launched immediately *unless* the
926ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // current foreground activity is marked as "immersive".
927d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    LogUtil.d("StatusBarNotifier.configureFullScreenIntent", "setting fullScreenIntent: " + intent);
928ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setFullScreenIntent(intent, true);
929ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
930ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
931ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private Notification.Builder getNotificationBuilder() {
932ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final Notification.Builder builder = new Notification.Builder(mContext);
933ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setOngoing(true);
934d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    builder.setOnlyAlertOnce(true);
93510b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian    // This will be ignored on O+ and handled by the channel
9362f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    // noinspection deprecation
93710b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian    builder.setPriority(Notification.PRIORITY_HIGH);
938ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
939ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return builder;
940ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
941ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
942d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private PendingIntent createLaunchPendingIntent(boolean isFullScreen) {
943ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Intent intent =
944ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        InCallActivity.getIntent(
945d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian            mContext, false /* showDialpad */, false /* newOutgoingCall */, isFullScreen);
946ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
947ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    int requestCode = PENDING_INTENT_REQUEST_CODE_NON_FULL_SCREEN;
948ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (isFullScreen) {
949ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Use a unique request code so that the pending intent isn't clobbered by the
950ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // non-full screen pending intent.
951ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      requestCode = PENDING_INTENT_REQUEST_CODE_FULL_SCREEN;
952ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
953ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
954ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // PendingIntent that can be used to launch the InCallActivity.  The
955ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // system fires off this intent if the user pulls down the windowshade
956ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // and clicks the notification's expanded view.  It's also used to
957ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // launch the InCallActivity immediately when when there's an incoming
958ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // call (see the "fullScreenIntent" field below).
959ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return PendingIntent.getActivity(mContext, requestCode, intent, 0);
960ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
961ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
962ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void setStatusBarCallListener(StatusBarCallListener listener) {
963ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mStatusBarCallListener != null) {
964ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mStatusBarCallListener.cleanup();
965ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
966ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mStatusBarCallListener = listener;
967ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
968ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
969ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private class StatusBarCallListener implements DialerCallListener {
970ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
971ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    private DialerCall mDialerCall;
972ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
973ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    StatusBarCallListener(DialerCall dialerCall) {
974ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mDialerCall = dialerCall;
975ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mDialerCall.addListener(this);
976ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
977ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
978ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    void cleanup() {
979ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mDialerCall.removeListener(this);
980ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
981ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
982ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
983ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onDialerCallDisconnect() {}
984ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
985ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
986ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onDialerCallUpdate() {
987ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (CallList.getInstance().getIncomingCall() == null) {
988ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        mDialerRingtoneManager.stopCallWaitingTone();
989ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
990ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
991ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
992ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
993ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onDialerCallChildNumberChange() {}
994ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
995ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
996ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onDialerCallLastForwardedNumberChange() {}
997ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
998ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
999ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onDialerCallUpgradeToVideo() {}
1000ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
1001ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
1002ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onWiFiToLteHandover() {}
1003ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
1004ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
1005ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void onHandoverToWifiFailure() {}
1006ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
1007c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian    @Override
1008c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian    public void onInternationalCallOnWifi() {}
1009c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian
10102f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    @Override
10112f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian    public void onEnrichedCallSessionUpdate() {}
10122f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian
1013ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    /**
1014ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     * Responds to changes in the session modification state for the call by dismissing the status
1015ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     * bar notification as required.
1016ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     */
1017ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
1018d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    public void onDialerCallSessionModificationStateChange() {
1019d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      if (mDialerCall.getVideoTech().getSessionModificationState()
10209050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian          == SessionModificationState.NO_REQUEST) {
1021ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        cleanup();
1022ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        updateNotification(CallList.getInstance());
1023ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
1024ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
1025ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
1026ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian}
1027