Merge changes Ibf79b70e,Iab1415b0

* changes:
  Only show the most recent call type icon in the new call log, instead of the last 3.
  Make incoming and ongoing call notification foreground and highest priority.
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
index e1ec0f6..40d922f 100644
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
@@ -54,7 +54,7 @@
           .append(AnnotatedCallLog.IS_VOICEMAIL + " integer, ")
           // Columns only in AnnotatedCallLog
           .append(AnnotatedCallLog.NUMBER + " blob, ")
-          .append(AnnotatedCallLog.TYPE + " integer")
+          .append(AnnotatedCallLog.CALL_TYPE + " integer")
           .append(");")
           .toString();
 
diff --git a/java/com/android/dialer/calllog/database/annotated_call_log.proto b/java/com/android/dialer/calllog/database/annotated_call_log.proto
deleted file mode 100644
index de2bc5f..0000000
--- a/java/com/android/dialer/calllog/database/annotated_call_log.proto
+++ /dev/null
@@ -1,15 +0,0 @@
-syntax = "proto2";
-
-option java_package = "com.android.dialer";
-option java_multiple_files = true;
-option optimize_for = LITE_RUNTIME;
-
-// DIALER_SCRUB.UNCOMMENT_IN_OPEN_SOURCE option optimize_for = LITE_RUNTIME;
-
-package com.android.dialer;
-
-// A list of android.provider.CallLog.Calls.TYPE values ordered from newest to
-// oldest.
-message CallTypes {
-  repeated int32 type = 1;
-}
diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
index 25950f6..d466da9 100644
--- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
+++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
@@ -148,6 +148,13 @@
      */
     String IS_VOICEMAIL = "is_voicemail";
 
+    /**
+     * Copied from {@link android.provider.CallLog.Calls#TYPE}.
+     *
+     * <p>Type: INTEGER (int)
+     */
+    String CALL_TYPE = "call_type";
+
     String[] ALL_COMMON_COLUMNS =
         new String[] {
           _ID,
@@ -165,7 +172,8 @@
           PHONE_ACCOUNT_COLOR,
           FEATURES,
           IS_BUSINESS,
-          IS_VOICEMAIL
+          IS_VOICEMAIL,
+          CALL_TYPE
         };
   }
 
@@ -196,13 +204,6 @@
      * <p>Type: BLOB
      */
     public static final String NUMBER = "number";
-
-    /**
-     * Copied from {@link android.provider.CallLog.Calls#TYPE}.
-     *
-     * <p>Type: INTEGER (int)
-     */
-    public static final String TYPE = "type";
   }
 
   /**
@@ -233,18 +234,10 @@
     public static final String NUMBER_CALLS = "number_calls";
 
     /**
-     * The call types of the most recent 3 calls, encoded as a CallTypes proto.
-     *
-     * <p>TYPE: BLOB
-     */
-    public static final String CALL_TYPES = "call_types";
-
-    /**
      * Columns that are only in the {@link CoalescedAnnotatedCallLog} but not the {@link
      * AnnotatedCallLog}.
      */
-    private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG =
-        new String[] {NUMBER_CALLS, CALL_TYPES};
+    private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG = new String[] {NUMBER_CALLS};
 
     /** All columns in the {@link CoalescedAnnotatedCallLog}. */
     public static final String[] ALL_COLUMNS =
diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
index 1bdbb8a..d6ad618 100644
--- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
@@ -38,9 +38,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.text.TextUtils;
 import android.util.ArraySet;
-import com.android.dialer.CallTypes;
 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
-import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
 import com.android.dialer.calllog.datasources.CallLogDataSource;
 import com.android.dialer.calllog.datasources.CallLogMutations;
 import com.android.dialer.calllog.datasources.util.RowCombiner;
@@ -153,30 +151,20 @@
   @Override
   public ContentValues coalesce(List<ContentValues> individualRowsSortedByTimestampDesc) {
     // TODO(zachh): Complete implementation.
-    ContentValues coalescedValues =
-        new RowCombiner(individualRowsSortedByTimestampDesc)
-            .useMostRecentLong(AnnotatedCallLog.TIMESTAMP)
-            .useMostRecentLong(AnnotatedCallLog.NEW)
-            .useMostRecentString(AnnotatedCallLog.NUMBER_TYPE_LABEL)
-            .useMostRecentString(AnnotatedCallLog.NAME)
-            .useMostRecentString(AnnotatedCallLog.FORMATTED_NUMBER)
-            .useMostRecentString(AnnotatedCallLog.PHOTO_URI)
-            .useMostRecentLong(AnnotatedCallLog.PHOTO_ID)
-            .useMostRecentString(AnnotatedCallLog.LOOKUP_URI)
-            .useMostRecentString(AnnotatedCallLog.GEOCODED_LOCATION)
-            .useSingleValueString(AnnotatedCallLog.PHONE_ACCOUNT_LABEL)
-            .useSingleValueLong(AnnotatedCallLog.PHONE_ACCOUNT_COLOR)
-            .combine();
-
-    CallTypes.Builder callTypes = CallTypes.newBuilder();
-    // Store a maximum of 3 call types since that's all we show to users via icons.
-    for (int i = 0; i < 3 && i < individualRowsSortedByTimestampDesc.size(); i++) {
-      callTypes.addType(
-          individualRowsSortedByTimestampDesc.get(i).getAsInteger(AnnotatedCallLog.TYPE));
-    }
-    coalescedValues.put(CoalescedAnnotatedCallLog.CALL_TYPES, callTypes.build().toByteArray());
-
-    return coalescedValues;
+    return new RowCombiner(individualRowsSortedByTimestampDesc)
+        .useMostRecentLong(AnnotatedCallLog.TIMESTAMP)
+        .useMostRecentLong(AnnotatedCallLog.NEW)
+        .useMostRecentString(AnnotatedCallLog.NUMBER_TYPE_LABEL)
+        .useMostRecentString(AnnotatedCallLog.NAME)
+        .useMostRecentString(AnnotatedCallLog.FORMATTED_NUMBER)
+        .useMostRecentString(AnnotatedCallLog.PHOTO_URI)
+        .useMostRecentLong(AnnotatedCallLog.PHOTO_ID)
+        .useMostRecentString(AnnotatedCallLog.LOOKUP_URI)
+        .useMostRecentString(AnnotatedCallLog.GEOCODED_LOCATION)
+        .useSingleValueString(AnnotatedCallLog.PHONE_ACCOUNT_LABEL)
+        .useSingleValueLong(AnnotatedCallLog.PHONE_ACCOUNT_COLOR)
+        .useMostRecentLong(AnnotatedCallLog.CALL_TYPE)
+        .combine();
   }
 
   @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
@@ -286,7 +274,7 @@
             contentValues.put(AnnotatedCallLog.NUMBER, numberAsProtoBytes);
           }
 
-          contentValues.put(AnnotatedCallLog.TYPE, type);
+          contentValues.put(AnnotatedCallLog.CALL_TYPE, type);
           contentValues.put(AnnotatedCallLog.NAME, cachedName);
           contentValues.put(AnnotatedCallLog.FORMATTED_NUMBER, formattedNumber);
           contentValues.put(AnnotatedCallLog.PHOTO_URI, cachedPhotoUri);
diff --git a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
index d893383..13a801a 100644
--- a/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
+++ b/java/com/android/dialer/calllog/ui/CoalescedAnnotatedCallLogCursorLoader.java
@@ -19,12 +19,8 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
 import android.support.v4.content.CursorLoader;
-import com.android.dialer.CallTypes;
 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
-import com.android.dialer.common.Assert;
-import com.google.protobuf.InvalidProtocolBufferException;
 
 /** CursorLoader for the coalesced annotated call log. */
 final class CoalescedAnnotatedCallLogCursorLoader extends CursorLoader {
@@ -47,8 +43,8 @@
   private static final int FEATURES = 13;
   private static final int IS_BUSINESS = 14;
   private static final int IS_VOICEMAIL = 15;
-  private static final int NUMBER_CALLS = 16;
-  private static final int CALL_TYPES = 17;
+  private static final int TYPE = 16;
+  private static final int NUMBER_CALLS = 17;
 
   /** Convenience class for accessing values using an abbreviated syntax. */
   static final class Row {
@@ -127,13 +123,8 @@
       return cursor.getInt(NUMBER_CALLS);
     }
 
-    @NonNull
-    CallTypes callTypes() {
-      try {
-        return CallTypes.parseFrom(cursor.getBlob(CALL_TYPES));
-      } catch (InvalidProtocolBufferException e) {
-        throw Assert.createAssertionFailException("Couldn't parse call types", e);
-      }
+    int callType() {
+      return cursor.getInt(TYPE);
     }
   }
 
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
index e198a38..8ac419e 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
@@ -66,8 +66,7 @@
     primaryTextView.setText(buildPrimaryText(row));
     secondaryTextView.setText(buildSecondaryText(row));
 
-    if (row.isNew()) {
-      // TODO(zachh): Figure out correct styling for new/missed/unread calls.
+    if (isNewMissedCall(row)) {
       primaryTextView.setTextAppearance(R.style.primary_textview_new_call);
       // TODO(zachh): Styling for call type icons when the call is new.
       secondaryTextView.setTextAppearance(R.style.secondary_textview_new_call);
@@ -95,6 +94,12 @@
     return primaryText.toString();
   }
 
+  private boolean isNewMissedCall(CoalescedAnnotatedCallLogCursorLoader.Row row) {
+    // Show missed call styling if the most recent call in the group was missed and it is still
+    // marked as NEW. It is not clear what IS_READ should be used for and it is currently not used.
+    return row.callType() == Calls.MISSED_TYPE && row.isNew();
+  }
+
   private String buildSecondaryText(CoalescedAnnotatedCallLogCursorLoader.Row row) {
     /*
      * Rules: (Duo video, )?$Label|$Location • Date
@@ -158,10 +163,9 @@
   }
 
   private void setSecondaryCallTypes(Row row) {
-    // Only call type icons are shown before the secondary text.
-    for (int callType : row.callTypes().getTypeList()) {
-      secondaryCallTypeIconsView.add(callType);
-    }
+    // Only call type icon is shown before the secondary text.
+    secondaryCallTypeIconsView.add(row.callType());
+
     // TODO(zachh): Per new mocks, may need to add method to CallTypeIconsView to disable coloring.
   }
 
diff --git a/java/com/android/dialer/database/CallLogQueryHandler.java b/java/com/android/dialer/database/CallLogQueryHandler.java
index 4867d9d..35250d6 100644
--- a/java/com/android/dialer/database/CallLogQueryHandler.java
+++ b/java/com/android/dialer/database/CallLogQueryHandler.java
@@ -54,12 +54,9 @@
    */
   public static final int CALL_TYPE_ALL = -1;
 
-  private static final String TAG = "CallLogQueryHandler";
   private static final int NUM_LOGS_TO_DISPLAY = 1000;
   /** The token for the query to fetch the old entries from the call log. */
   private static final int QUERY_CALLLOG_TOKEN = 54;
-  /** The token for the query to mark all missed calls as old after seeing the call log. */
-  private static final int UPDATE_MARK_AS_OLD_TOKEN = 55;
   /** The token for the query to mark all missed calls as read after seeing the call log. */
   private static final int UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN = 56;
   /** The token for the query to fetch voicemail status messages. */
@@ -82,7 +79,7 @@
       Context context, ContentResolver contentResolver, Listener listener, int limit) {
     super(contentResolver);
     mContext = context.getApplicationContext();
-    mListener = new WeakReference<Listener>(listener);
+    mListener = new WeakReference<>(listener);
     mLogLimit = limit;
   }
 
@@ -107,10 +104,6 @@
     }
   }
 
-  public void fetchCalls(int callType) {
-    fetchCalls(callType, 0);
-  }
-
   public void fetchVoicemailStatus() {
     StringBuilder where = new StringBuilder();
     List<String> selectionArgs = new ArrayList<>();
@@ -226,28 +219,6 @@
     cancelOperation(QUERY_CALLLOG_TOKEN);
   }
 
-  /** Updates all new calls to mark them as old. */
-  public void markNewCallsAsOld() {
-    if (!PermissionsUtil.hasPhonePermissions(mContext)) {
-      return;
-    }
-    // Mark all "new" calls as not new anymore.
-    StringBuilder where = new StringBuilder();
-    where.append(Calls.NEW);
-    where.append(" = 1");
-
-    ContentValues values = new ContentValues(1);
-    values.put(Calls.NEW, "0");
-
-    startUpdate(
-        UPDATE_MARK_AS_OLD_TOKEN,
-        null,
-        TelecomUtil.getCallLogUri(mContext),
-        values,
-        where.toString(),
-        null);
-  }
-
   /** Updates all missed calls to mark them as read. */
   public void markMissedCallsAsRead() {
     if (!PermissionsUtil.hasPhonePermissions(mContext)) {
@@ -316,19 +287,19 @@
    */
   private boolean updateAdapterData(Cursor cursor) {
     final Listener listener = mListener.get();
-    if (listener != null) {
-      return listener.onCallsFetched(cursor);
-    }
-    return false;
+    return listener != null && listener.onCallsFetched(cursor);
   }
 
   /** @return Query string to get all unread missed calls. */
   private String getUnreadMissedCallsQuery() {
-    StringBuilder where = new StringBuilder();
-    where.append(Calls.IS_READ).append(" = 0 OR ").append(Calls.IS_READ).append(" IS NULL");
-    where.append(" AND ");
-    where.append(Calls.TYPE).append(" = ").append(Calls.MISSED_TYPE);
-    return where.toString();
+    return Calls.IS_READ
+        + " = 0 OR "
+        + Calls.IS_READ
+        + " IS NULL"
+        + " AND "
+        + Calls.TYPE
+        + " = "
+        + Calls.MISSED_TYPE;
   }
 
   private void updateVoicemailStatus(Cursor statusCursor) {
@@ -365,7 +336,7 @@
     void onMissedCallsUnreadCountFetched(Cursor cursor);
 
     /**
-     * Called when {@link CallLogQueryHandler#fetchCalls(int)} complete. Returns true if takes
+     * Called when {@link CallLogQueryHandler#fetchCalls(int, long)} complete. Returns true if takes
      * ownership of cursor.
      */
     boolean onCallsFetched(Cursor combinedCursor);
@@ -375,9 +346,9 @@
    * Simple handler that wraps background calls to catch {@link SQLiteException}, such as when the
    * disk is full.
    */
-  protected class CatchingWorkerHandler extends AsyncQueryHandler.WorkerHandler {
+  private class CatchingWorkerHandler extends AsyncQueryHandler.WorkerHandler {
 
-    public CatchingWorkerHandler(Looper looper) {
+    CatchingWorkerHandler(Looper looper) {
       super(looper);
     }
 
@@ -386,11 +357,7 @@
       try {
         // Perform same query while catching any exceptions
         super.handleMessage(msg);
-      } catch (SQLiteDiskIOException e) {
-        LogUtil.e("CallLogQueryHandler.handleMessage", "exception on background worker thread", e);
-      } catch (SQLiteFullException e) {
-        LogUtil.e("CallLogQueryHandler.handleMessage", "exception on background worker thread", e);
-      } catch (SQLiteDatabaseCorruptException e) {
+      } catch (SQLiteDiskIOException | SQLiteFullException | SQLiteDatabaseCorruptException e) {
         LogUtil.e("CallLogQueryHandler.handleMessage", "exception on background worker thread", e);
       } catch (IllegalArgumentException e) {
         LogUtil.e("CallLogQueryHandler.handleMessage", "contactsProvider not present on device", e);
diff --git a/java/com/android/dialer/notification/NotificationChannelManager.java b/java/com/android/dialer/notification/NotificationChannelManager.java
index 790aac3..93caed5 100644
--- a/java/com/android/dialer/notification/NotificationChannelManager.java
+++ b/java/com/android/dialer/notification/NotificationChannelManager.java
@@ -133,7 +133,7 @@
         new NotificationChannel(
             NotificationChannelId.ONGOING_CALL,
             context.getText(R.string.notification_channel_ongoing_call),
-            NotificationManager.IMPORTANCE_DEFAULT);
+            NotificationManager.IMPORTANCE_MAX);
     channel.setShowBadge(false);
     channel.enableLights(false);
     channel.enableVibration(false);
diff --git a/java/com/android/incallui/NotificationBroadcastReceiver.java b/java/com/android/incallui/NotificationBroadcastReceiver.java
index f83f84d..52d01f5 100644
--- a/java/com/android/incallui/NotificationBroadcastReceiver.java
+++ b/java/com/android/incallui/NotificationBroadcastReceiver.java
@@ -72,19 +72,19 @@
 
     // TODO: Commands of this nature should exist in the CallList.
     if (action.equals(ACTION_ANSWER_VIDEO_INCOMING_CALL)) {
-      answerIncomingCall(context, VideoProfile.STATE_BIDIRECTIONAL);
+      answerIncomingCall(VideoProfile.STATE_BIDIRECTIONAL);
     } else if (action.equals(ACTION_ANSWER_VOICE_INCOMING_CALL)) {
-      answerIncomingCall(context, VideoProfile.STATE_AUDIO_ONLY);
+      answerIncomingCall(VideoProfile.STATE_AUDIO_ONLY);
     } else if (action.equals(ACTION_DECLINE_INCOMING_CALL)) {
       Logger.get(context)
           .logImpression(DialerImpression.Type.REJECT_INCOMING_CALL_FROM_NOTIFICATION);
-      declineIncomingCall(context);
+      declineIncomingCall();
     } else if (action.equals(ACTION_HANG_UP_ONGOING_CALL)) {
-      hangUpOngoingCall(context);
+      hangUpOngoingCall();
     } else if (action.equals(ACTION_ACCEPT_VIDEO_UPGRADE_REQUEST)) {
       acceptUpgradeRequest(context);
     } else if (action.equals(ACTION_DECLINE_VIDEO_UPGRADE_REQUEST)) {
-      declineUpgradeRequest(context);
+      declineUpgradeRequest();
     } else if (action.equals(ACTION_PULL_EXTERNAL_CALL)) {
       context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
       int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
@@ -99,7 +99,7 @@
   private void acceptUpgradeRequest(Context context) {
     CallList callList = InCallPresenter.getInstance().getCallList();
     if (callList == null) {
-      StatusBarNotifier.clearAllCallNotifications(context);
+      StatusBarNotifier.clearAllCallNotifications();
       LogUtil.e("NotificationBroadcastReceiver.acceptUpgradeRequest", "call list is empty");
     } else {
       DialerCall call = callList.getVideoUpgradeRequestCall();
@@ -109,10 +109,10 @@
     }
   }
 
-  private void declineUpgradeRequest(Context context) {
+  private void declineUpgradeRequest() {
     CallList callList = InCallPresenter.getInstance().getCallList();
     if (callList == null) {
-      StatusBarNotifier.clearAllCallNotifications(context);
+      StatusBarNotifier.clearAllCallNotifications();
       LogUtil.e("NotificationBroadcastReceiver.declineUpgradeRequest", "call list is empty");
     } else {
       DialerCall call = callList.getVideoUpgradeRequestCall();
@@ -122,10 +122,10 @@
     }
   }
 
-  private void hangUpOngoingCall(Context context) {
+  private void hangUpOngoingCall() {
     CallList callList = InCallPresenter.getInstance().getCallList();
     if (callList == null) {
-      StatusBarNotifier.clearAllCallNotifications(context);
+      StatusBarNotifier.clearAllCallNotifications();
       LogUtil.e("NotificationBroadcastReceiver.hangUpOngoingCall", "call list is empty");
     } else {
       DialerCall call = callList.getOutgoingCall();
@@ -140,10 +140,10 @@
     }
   }
 
-  private void answerIncomingCall(Context context, int videoState) {
+  private void answerIncomingCall(int videoState) {
     CallList callList = InCallPresenter.getInstance().getCallList();
     if (callList == null) {
-      StatusBarNotifier.clearAllCallNotifications(context);
+      StatusBarNotifier.clearAllCallNotifications();
       LogUtil.e("NotificationBroadcastReceiver.answerIncomingCall", "call list is empty");
     } else {
       DialerCall call = callList.getIncomingCall();
@@ -155,10 +155,10 @@
     }
   }
 
-  private void declineIncomingCall(Context context) {
+  private void declineIncomingCall() {
     CallList callList = InCallPresenter.getInstance().getCallList();
     if (callList == null) {
-      StatusBarNotifier.clearAllCallNotifications(context);
+      StatusBarNotifier.clearAllCallNotifications();
       LogUtil.e("NotificationBroadcastReceiver.declineIncomingCall", "call list is empty");
     } else {
       DialerCall call = callList.getIncomingCall();
diff --git a/java/com/android/incallui/StatusBarNotifier.java b/java/com/android/incallui/StatusBarNotifier.java
index becfad4..86ad9ff 100644
--- a/java/com/android/incallui/StatusBarNotifier.java
+++ b/java/com/android/incallui/StatusBarNotifier.java
@@ -28,7 +28,6 @@
 import static com.android.incallui.NotificationBroadcastReceiver.ACTION_TURN_ON_SPEAKER;
 
 import android.Manifest;
-import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -74,7 +73,6 @@
 import com.android.dialer.lettertile.LetterTileDrawable;
 import com.android.dialer.lettertile.LetterTileDrawable.ContactType;
 import com.android.dialer.multimedia.MultimediaData;
-import com.android.dialer.notification.DialerNotificationManager;
 import com.android.dialer.notification.NotificationChannelId;
 import com.android.dialer.oem.MotorolaUtils;
 import com.android.dialer.util.DrawableConverter;
@@ -86,12 +84,12 @@
 import com.android.incallui.call.CallList;
 import com.android.incallui.call.DialerCall;
 import com.android.incallui.call.DialerCallListener;
+import com.android.incallui.call.TelecomAdapter;
 import com.android.incallui.ringtone.DialerRingtoneManager;
 import com.android.incallui.ringtone.InCallTonePlayer;
 import com.android.incallui.ringtone.ToneGeneratorFactory;
 import com.android.incallui.videotech.utils.SessionModificationState;
 import java.util.List;
-import java.util.Locale;
 import java.util.Objects;
 
 /** This class adds Notifications to the status bar for the in-call experience. */
@@ -100,7 +98,6 @@
         EnrichedCallManager.StateChangedListener,
         AudioModeProvider.AudioModeListener {
 
-  private static final String NOTIFICATION_TAG = "STATUS_BAR_NOTIFIER";
   private static final int NOTIFICATION_ID = 1;
 
   // Notification types
@@ -146,12 +143,12 @@
    * Should only be called from a irrecoverable state where it is necessary to dismiss all
    * notifications.
    */
-  static void clearAllCallNotifications(Context context) {
+  static void clearAllCallNotifications() {
     LogUtil.e(
         "StatusBarNotifier.clearAllCallNotifications",
         "something terrible happened, clear all InCall notifications");
 
-    DialerNotificationManager.cancel(context, NOTIFICATION_TAG, NOTIFICATION_ID);
+    TelecomAdapter.getInstance().stopForegroundNotification();
   }
 
   private static int getWorkStringFromPersonalString(int resId) {
@@ -219,10 +216,9 @@
       setStatusBarCallListener(null);
     }
     if (mCurrentNotification != NOTIFICATION_NONE) {
-      LogUtil.i("StatusBarNotifier.cancelNotification", "cancel");
-      DialerNotificationManager.cancel(mContext, NOTIFICATION_TAG, NOTIFICATION_ID);
+      TelecomAdapter.getInstance().stopForegroundNotification();
+      mCurrentNotification = NOTIFICATION_NONE;
     }
-    mCurrentNotification = NOTIFICATION_NONE;
   }
 
   /**
@@ -390,7 +386,7 @@
               "Canceling old notification so this one can be noisy");
           // Moving from a non-interuptive notification (or none) to a noisy one. Cancel the old
           // notification (if there is one) so the fullScreenIntent or HUN will show
-          DialerNotificationManager.cancel(mContext, NOTIFICATION_TAG, NOTIFICATION_ID);
+          TelecomAdapter.getInstance().stopForegroundNotification();
         }
         break;
       case NOTIFICATION_INCOMING_CALL_QUIET:
@@ -404,6 +400,8 @@
           builder.setColorized(true);
           builder.setChannelId(NotificationChannelId.ONGOING_CALL);
         }
+        // This will be ignored on O+ and handled by the channel
+        builder.setPriority(Notification.PRIORITY_MAX);
         break;
       default:
         break;
@@ -414,8 +412,7 @@
     builder.setSmallIcon(iconResId);
     builder.setContentTitle(contentTitle);
     builder.setLargeIcon(largeIcon);
-    builder.setColor(
-        mContext.getResources().getColor(R.color.dialer_theme_color, mContext.getTheme()));
+    builder.setColor(InCallPresenter.getInstance().getThemeColorManager().getPrimaryColor());
 
     if (isVideoUpgradeRequest) {
       builder.setUsesChronometer(false);
@@ -451,22 +448,9 @@
         "StatusBarNotifier.buildAndSendNotification",
         "displaying notification for " + notificationType);
 
-    try {
-      DialerNotificationManager.notify(mContext, NOTIFICATION_TAG, NOTIFICATION_ID, notification);
-    } catch (RuntimeException e) {
-      // TODO(b/34744003): Move the memory stats into silent feedback PSD.
-      ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
-      ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
-      activityManager.getMemoryInfo(memoryInfo);
-      throw new RuntimeException(
-          String.format(
-              Locale.US,
-              "Error displaying notification with photo type: %d (low memory? %b, availMem: %d)",
-              contactInfo.photoType,
-              memoryInfo.lowMemory,
-              memoryInfo.availMem),
-          e);
-    }
+    // If a notification exists, this will only update it.
+    TelecomAdapter.getInstance().startForegroundNotification(NOTIFICATION_ID, notification);
+
     Trace.endSection();
     call.getLatencyReport().onNotificationShown();
     mCurrentNotification = notificationType;
diff --git a/java/com/android/incallui/call/TelecomAdapter.java b/java/com/android/incallui/call/TelecomAdapter.java
index 005278b..0c0bbd4 100644
--- a/java/com/android/incallui/call/TelecomAdapter.java
+++ b/java/com/android/incallui/call/TelecomAdapter.java
@@ -16,12 +16,14 @@
 
 package com.android.incallui.call;
 
+import android.app.Notification;
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.os.Looper;
 import android.support.annotation.MainThread;
 import android.support.annotation.VisibleForTesting;
 import android.telecom.InCallService;
+import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
 import java.util.List;
 
@@ -167,4 +169,24 @@
     }
     return false;
   }
+
+  /**
+   * Start a foreground notification. Calling it multiple times with the same id only updates the
+   * existing notification. Whoever called this function are responsible for calling {@link
+   * #stopForegroundNotification()} to remove the notification.
+   */
+  public void startForegroundNotification(int id, Notification notification) {
+    Assert.isNotNull(
+        mInCallService, "No inCallService available for starting foreground notification");
+    mInCallService.startForeground(id, notification);
+  }
+
+  /**
+   * Stop a started foreground notification. This does not stop {@code mInCallService} from running.
+   */
+  public void stopForegroundNotification() {
+    Assert.isNotNull(
+        mInCallService, "No inCallService available for stopping foreground notification");
+    mInCallService.stopForeground(true /*removeNotification*/);
+  }
 }