Update AlertDialogs UI

Fix: 147614686
Fix: 147615554

Test: Manual

Change-Id: I600220e2ac723ea98012cdb39e26e5a8590f2e7d
(cherry picked from commit cb0a7a8300a7b5ef4d7ce2300787c9755fe50ee4)
diff --git a/res/color/icon_accent_activatable.xml b/res/color/icon_accent_activatable.xml
index cf4b9e7..c652f07 100644
--- a/res/color/icon_accent_activatable.xml
+++ b/res/color/icon_accent_activatable.xml
@@ -16,6 +16,6 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:color="@color/primary_icon_color"
           android:state_activated="false"/>
-    <item android:color="?android:colorAccent"
+    <item android:color="@color/audio_output_accent"
           android:state_activated="true"/>
 </selector>
diff --git a/res/color/text_accent_activatable.xml b/res/color/text_accent_activatable.xml
deleted file mode 100644
index 4f1dc0f..0000000
--- a/res/color/text_accent_activatable.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/primary_text_color"
-          android:state_activated="false"/>
-    <item android:color="?android:colorAccent"
-          android:state_activated="true"/>
-</selector>
diff --git a/res/layout/add_favorite_number_list_item.xml b/res/layout/add_favorite_number_list_item.xml
deleted file mode 100644
index ffe5445..0000000
--- a/res/layout/add_favorite_number_list_item.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/add_favorite_number_list_height"
-    android:background="?android:attr/selectableItemBackground"
-    android:paddingStart="@dimen/add_favorite_number_list_padding"
-    android:paddingEnd="@dimen/add_favorite_number_list_padding">
-
-    <TextView
-        android:id="@+id/phone_number"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.AddFavoriteNumberTitle"
-        android:duplicateParentState="true"
-        app:layout_constraintVertical_chainStyle="packed"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@+id/phone_number_description"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/phone_number_checkbox"/>
-
-    <TextView
-        android:id="@+id/phone_number_description"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.AddFavoriteNumberSubtitle"
-        android:duplicateParentState="true"
-        app:layout_constraintTop_toBottomOf="@id/phone_number"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toStartOf="@id/phone_number_checkbox"/>
-
-    <ImageView
-        android:id="@+id/phone_number_checkbox"
-        android:src="@drawable/ic_favorite_activatable"
-        android:layout_width="@dimen/primary_icon_size"
-        android:layout_height="@dimen/primary_icon_size"
-        android:tint="@color/primary_icon_selector"
-        android:duplicateParentState="true"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/audio_route_list_item.xml b/res/layout/audio_route_list_item.xml
deleted file mode 100644
index c1510ef..0000000
--- a/res/layout/audio_route_list_item.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/audio_route_height"
-    android:background="?android:attr/selectableItemBackground"
-    android:elevation="@dimen/dialer_card_elevation">
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/text_start"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_begin="@dimen/audio_route_constraint_guide_begin"/>
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="@dimen/audio_route_icon_size"
-        android:layout_height="@dimen/audio_route_icon_size"
-        android:scaleType="fitCenter"
-        android:layout_marginStart="@dimen/audio_route_content_padding"
-        android:tint="@color/icon_accent_activatable"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"/>
-    <TextView
-        android:id="@+id/body"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:textColor="@color/text_accent_activatable"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="@+id/text_start"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"/>
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/audio_route_switch_dialog.xml b/res/layout/audio_route_switch_dialog.xml
deleted file mode 100644
index 7a5013c..0000000
--- a/res/layout/audio_route_switch_dialog.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<androidx.recyclerview.widget.RecyclerView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/list"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false"/>
diff --git a/res/layout/phone_number_list_item.xml b/res/layout/phone_number_list_item.xml
deleted file mode 100644
index 04e1b61..0000000
--- a/res/layout/phone_number_list_item.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.car.dialer.widget.CheckableRelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingStart="?android:listPreferredItemPaddingStart"
-    android:paddingEnd="?android:listPreferredItemPaddingEnd">
-
-    <RadioButton
-        android:id="@+id/phone_number_checkbox"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginEnd="@dimen/phone_number_radio_list_padding"/>
-    <TextView
-        android:id="@+id/phone_number"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_toEndOf="@id/phone_number_checkbox"
-        android:textAppearance="?android:attr/textAppearanceMedium"/>
-    <TextView
-        android:id="@+id/phone_number_description"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/phone_number"
-        android:layout_toEndOf="@id/phone_number_checkbox"
-        android:textAppearance="?android:attr/textAppearanceSmall"/>
-
-</com.android.car.dialer.widget.CheckableRelativeLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 5f6707d..49d2e52 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -18,6 +18,7 @@
     <color name="phone_call">@*android:color/car_green_700</color>
     <color name="phone_end_call">@*android:color/car_red_500a</color>
     <color name="onhold_call_background">@*android:color/car_grey_868</color>
+    <color name="audio_output_accent">@*android:color/car_accent</color>
 
     <!-- Dialpad page -->
     <color name="call_button_outline">@*android:color/car_green_500</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 010fca4..edc9bc3 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -17,13 +17,10 @@
     <!-- Dialer -->
     <dimen name="dialer_card_elevation">2dp</dimen>
 
-    <!-- Audio route dimentions -->
-    <dimen name="audio_route_height">@dimen/control_bar_height</dimen>
-    <dimen name="audio_route_content_padding">@dimen/list_item_padding</dimen>
-    <dimen name="audio_route_icon_size">@dimen/primary_icon_size</dimen>
+    <!-- TODO: UNUSED! REMOVE THIS. b/149125789-->
     <dimen name="audio_route_constraint_guide_begin">@dimen/list_item_guideline</dimen>
 
-    <!-- Call list dimentions -->
+    <!-- Call list dimensions -->
     <dimen name="call_history_item_height">@dimen/list_item_height</dimen>
     <dimen name="call_history_item_padding">@dimen/list_item_padding</dimen>
     <dimen name="call_history_guideline_begin">@dimen/list_item_guideline_begin</dimen>
@@ -99,10 +96,6 @@
     <dimen name="favorite_card_space_vertical">@*android:dimen/car_padding_2</dimen>
     <dimen name="favorites_avatar_margin_bottom">@*android:dimen/car_padding_3</dimen>
 
-    <!-- Add faovirte flow dimensions -->
-    <dimen name="add_favorite_number_list_height">@dimen/list_item_height</dimen>
-    <dimen name="add_favorite_number_list_padding">@dimen/list_item_padding</dimen>
-
     <dimen name="call_fab_elevation">8dp</dimen>
     <dimen name="bksp_button_width">@dimen/touch_target_size</dimen>
 
@@ -145,7 +138,6 @@
     <dimen name="touch_target_width">156dp</dimen>
     <dimen name="subheader_list_height">76dp</dimen>
     <dimen name="control_bar_height">96dp</dimen>
-    <dimen name="phone_number_radio_list_padding">@*android:dimen/car_padding_2</dimen>
 
     <!-- Loading status view dimensions -->
     <dimen name="loading_info_icon_size">56dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 490b564..a890cd1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -205,4 +205,8 @@
     <string name="given_name_first_title">First name</string>
     <!-- Title of family name [CHAR LIMIT=40]-->
     <string name="family_name_first_title">Last name</string>
+
+    <!-- Audio route selection dialog. Placeholder resources for overriding -->
+    <string name="audio_route_dialog_title">Output call audio to:</string>
+    <string name="audio_route_dialog_subtitle"></string>
 </resources>
diff --git a/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragment.java b/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragment.java
index ad01d06..bae306b 100644
--- a/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragment.java
+++ b/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragment.java
@@ -17,11 +17,13 @@
 package com.android.car.dialer.ui.activecall;
 
 import android.app.AlertDialog;
-import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.telecom.Call;
 import android.telecom.CallAudioState;
 import android.telecom.CallAudioState.CallAudioRoute;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -36,16 +38,19 @@
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModelProviders;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.car.apps.common.util.ViewUtils;
 import com.android.car.dialer.R;
 import com.android.car.dialer.log.L;
 import com.android.car.dialer.telecom.UiCallManager;
+import com.android.car.ui.AlertDialogBuilder;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
 
 import com.google.common.collect.ImmutableMap;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /** A Fragment of the bar which controls on going call. */
@@ -73,7 +78,6 @@
                     .build();
 
     private AlertDialog mAudioRouteSelectionDialog;
-    private AudioRouteListAdapter mAudioRouteAdapter;
     private View mMuteButton;
     private View mAudioRouteView;
     private ImageView mAudioRouteButton;
@@ -83,24 +87,65 @@
     private MutableLiveData<Boolean> mDialpadState;
     private LiveData<List<Call>> mCallListLiveData;
     private int mPrimaryCallState;
+    private int mActiveRoute;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        View dialogView = LayoutInflater.from(getContext()).inflate(
-                R.layout.audio_route_switch_dialog, null, false);
-        RecyclerView list = dialogView.findViewById(R.id.list);
-        list.setLayoutManager(new LinearLayoutManager(getContext()));
-
-        mAudioRouteSelectionDialog = new AlertDialog.Builder(getContext())
-                .setView(dialogView)
-                .create();
-
         List<Integer> availableRoutes = UiCallManager.get().getSupportedAudioRoute();
-        int activeRoute = UiCallManager.get().getAudioRoute();
-        mAudioRouteAdapter = new AudioRouteListAdapter(getContext(), availableRoutes, activeRoute);
-        list.setAdapter(mAudioRouteAdapter);
+        mActiveRoute = UiCallManager.get().getAudioRoute();
+
+        if (availableRoutes.contains(CallAudioState.ROUTE_EARPIECE)
+                && availableRoutes.contains(CallAudioState.ROUTE_WIRED_HEADSET)) {
+            // Keep either ROUTE_EARPIECE or ROUTE_WIRED_HEADSET, but not both of them.
+            availableRoutes.remove(CallAudioState.ROUTE_WIRED_HEADSET);
+        }
+
+        List<CarUiListItem> listItems = new ArrayList<>();
+        CarUiListItemAdapter adapter = new CarUiListItemAdapter(listItems);
+
+        for (Integer audioRoute : availableRoutes) {
+            CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
+            AudioRouteInfo routeInfo = getAudioRouteInfo(audioRoute);
+            Drawable drawable = getResources().getDrawable(routeInfo.mIcon, null);
+            drawable.setTintList(
+                    getResources().getColorStateList(R.color.icon_accent_activatable, null));
+            item.setIcon(drawable);
+            item.setOnItemClickedListener((i) -> {
+                onSetAudioRoute(audioRoute);
+                // Reset the spannable titles for each item
+                for (CarUiListItem listItem : listItems) {
+                    CarUiContentListItem contentItem = (CarUiContentListItem) listItem;
+                    CharSequence title = contentItem.getTitle();
+                    contentItem.setTitle(title.toString());
+                    contentItem.setActivated(false);
+                }
+                i.setActivated(true);
+                // Set the spannable title for clicked item
+                String routeTitle = getString(routeInfo.mLabel);
+                item.setTitle(mActiveRoute == audioRoute
+                        ? withAccentColor(routeTitle)
+                        : routeTitle);
+                adapter.notifyDataSetChanged();
+            });
+            String routeTitle = getString(routeInfo.mLabel);
+
+            item.setTitle(mActiveRoute == audioRoute ? withAccentColor(routeTitle) : routeTitle);
+            item.setActivated(mActiveRoute == audioRoute);
+            listItems.add(item);
+        }
+
+        AlertDialogBuilder audioRouteSelectionDialogBuilder = new AlertDialogBuilder(getContext())
+                .setAdapter(adapter)
+                .setTitle(getString(R.string.audio_route_dialog_title));
+
+        String subtitle = getString(R.string.audio_route_dialog_subtitle);
+        if (!subtitle.isEmpty()) {
+            audioRouteSelectionDialogBuilder.setSubtitle(subtitle);
+        }
+
+        mAudioRouteSelectionDialog = audioRouteSelectionDialogBuilder.create();
 
         InCallViewModel inCallViewModel = ViewModelProviders.of(getActivity()).get(
                 InCallViewModel.class);
@@ -147,7 +192,6 @@
         if (audioRoutes.size() > 1) {
             mAudioRouteView.setOnClickListener((v) -> {
                 mAudioRouteView.setActivated(true);
-                mAudioRouteAdapter.setActiveAudioRoute(UiCallManager.get().getAudioRoute());
                 mAudioRouteSelectionDialog.show();
             });
         }
@@ -179,6 +223,14 @@
         }
     }
 
+    private CharSequence withAccentColor(String routeTitle) {
+        ForegroundColorSpan activeRouteSpan = new ForegroundColorSpan(
+                getResources().getColor(R.color.audio_output_accent, null));
+        SpannableString spannableTitle = new SpannableString(routeTitle);
+        spannableTitle.setSpan(activeRouteSpan, 0, routeTitle.length(), 0);
+        return spannableTitle;
+    }
+
     /** Set the call state and change the view for the pause button accordingly */
     private void setCallState(int callState) {
         L.d(TAG, "Call State: %s", callState);
@@ -224,17 +276,16 @@
 
     private void onSetAudioRoute(@CallAudioRoute int audioRoute) {
         UiCallManager.get().setAudioRoute(audioRoute);
+        mActiveRoute = audioRoute;
         mAudioRouteSelectionDialog.dismiss();
     }
 
     private void updateViewBasedOnAudioRoute(@Nullable Integer audioRoute) {
         if (audioRoute == null) {
-            mAudioRouteAdapter.setActiveAudioRoute(0);
             return;
         }
 
         L.i(TAG, "Audio Route State: " + audioRoute);
-        mAudioRouteAdapter.setActiveAudioRoute(audioRoute.intValue());
 
         AudioRouteInfo audioRouteInfo = getAudioRouteInfo(audioRoute);
         if (mAudioRouteButton != null) {
@@ -277,64 +328,4 @@
             mIconActivatable = iconActivatable;
         }
     }
-
-    private class AudioRouteListAdapter extends
-            RecyclerView.Adapter<AudioRouteItemViewHolder> {
-        private List<Integer> mSupportedRoutes;
-        private Context mContext;
-        private int mActiveAudioRoute;
-
-        AudioRouteListAdapter(Context context,
-                List<Integer> supportedRoutes,
-                int activeAudioRoute) {
-            mSupportedRoutes = supportedRoutes;
-            mActiveAudioRoute = activeAudioRoute;
-            mContext = context;
-            if (mSupportedRoutes.contains(CallAudioState.ROUTE_EARPIECE)
-                    && mSupportedRoutes.contains(CallAudioState.ROUTE_WIRED_HEADSET)) {
-                // Keep either ROUTE_EARPIECE or ROUTE_WIRED_HEADSET, but not both of them.
-                mSupportedRoutes.remove(CallAudioState.ROUTE_WIRED_HEADSET);
-            }
-        }
-
-        public void setActiveAudioRoute(int route) {
-            if (mActiveAudioRoute != route) {
-                mActiveAudioRoute = route;
-                notifyDataSetChanged();
-            }
-        }
-
-        @Override
-        public AudioRouteItemViewHolder onCreateViewHolder(ViewGroup container, int position) {
-            View listItemView = LayoutInflater.from(mContext).inflate(
-                    R.layout.audio_route_list_item, container, false);
-            return new AudioRouteItemViewHolder(listItemView);
-        }
-
-        @Override
-        public void onBindViewHolder(AudioRouteItemViewHolder viewHolder, int position) {
-            int audioRoute = mSupportedRoutes.get(position);
-            AudioRouteInfo routeInfo = getAudioRouteInfo(audioRoute);
-            viewHolder.mBody.setText(routeInfo.mLabel);
-            viewHolder.mIcon.setImageResource(routeInfo.mIcon);
-            viewHolder.itemView.setActivated(audioRoute == mActiveAudioRoute);
-            viewHolder.itemView.setOnClickListener((v) -> onSetAudioRoute(audioRoute));
-        }
-
-        @Override
-        public int getItemCount() {
-            return mSupportedRoutes.size();
-        }
-    }
-
-    private static class AudioRouteItemViewHolder extends RecyclerView.ViewHolder {
-        public final ImageView mIcon;
-        public final TextView mBody;
-
-        public AudioRouteItemViewHolder(View itemView) {
-            super(itemView);
-            mIcon = itemView.findViewById(R.id.icon);
-            mBody = itemView.findViewById(R.id.body);
-        }
-    }
 }
diff --git a/src/com/android/car/dialer/ui/common/DialerUtils.java b/src/com/android/car/dialer/ui/common/DialerUtils.java
index 01e6931..5826e42 100644
--- a/src/com/android/car/dialer/ui/common/DialerUtils.java
+++ b/src/com/android/car/dialer/ui/common/DialerUtils.java
@@ -28,6 +28,8 @@
 import com.android.car.telephony.common.PhoneNumber;
 import com.android.car.telephony.common.TelecomUtils;
 import com.android.car.ui.AlertDialogBuilder;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItem;
+import com.android.car.ui.recyclerview.CarUiRadioButtonListItemAdapter;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -45,8 +47,9 @@
     public interface PhoneNumberSelectionCallback {
         /**
          * Called when a phone number is chosen.
+         *
          * @param phoneNumber The phone number
-         * @param always Whether the user pressed "aways" or "just once"
+         * @param always      Whether the user pressed "aways" or "just once"
          */
         void onPhoneNumberSelected(PhoneNumber phoneNumber, boolean always);
     }
@@ -58,16 +61,28 @@
     public static void showPhoneNumberSelector(Context context,
             List<PhoneNumber> numbers,
             PhoneNumberSelectionCallback callback) {
+
         final List<PhoneNumber> selectedPhoneNumber = new ArrayList<>();
+        List<CarUiRadioButtonListItem> items = new ArrayList<>();
+        CarUiRadioButtonListItemAdapter adapter = new CarUiRadioButtonListItemAdapter(items);
+
+        for (PhoneNumber number : numbers) {
+            CharSequence readableLabel = number.getReadableLabel(context.getResources());
+            CarUiRadioButtonListItem item = new CarUiRadioButtonListItem();
+            item.setTitle(number.isPrimary()
+                    ? context.getString(R.string.primary_number_description, readableLabel)
+                    : readableLabel);
+            item.setBody(number.getNumber());
+            item.setOnCheckedChangeListener((i, isChecked) -> {
+                selectedPhoneNumber.clear();
+                selectedPhoneNumber.add(number);
+            });
+            items.add(item);
+        }
+
         new AlertDialogBuilder(context)
                 .setTitle(R.string.select_number_dialog_title)
-                .setSingleChoiceItems(
-                        new PhoneNumberListAdapter(context, numbers),
-                        -1,
-                        ((dialog, which) -> {
-                            selectedPhoneNumber.clear();
-                            selectedPhoneNumber.add(numbers.get(which));
-                        }))
+                .setSingleChoiceItems(adapter, null)
                 .setNeutralButton(R.string.select_number_dialog_just_once_button,
                         (dialog, which) -> {
                             if (!selectedPhoneNumber.isEmpty()) {
diff --git a/src/com/android/car/dialer/ui/common/FavoritePhoneNumberListAdapter.java b/src/com/android/car/dialer/ui/common/FavoritePhoneNumberListAdapter.java
deleted file mode 100644
index 9e7c652..0000000
--- a/src/com/android/car/dialer/ui/common/FavoritePhoneNumberListAdapter.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.dialer.ui.common;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-
-import com.android.car.dialer.R;
-import com.android.car.telephony.common.Contact;
-import com.android.car.telephony.common.PhoneNumber;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * {@link BaseAdapter} that presents the {@link PhoneNumber} and its type as two line list item with
- * stars to indicate favorite state or user selection to add to favorite. Currently favorite phone
- * number is set to disabled so user can not take any action for an existing favorite phone number.
- */
-public class FavoritePhoneNumberListAdapter extends BaseAdapter {
-    private final Context mContext;
-    private final FavoritePhoneNumberPresenter mFavoritePhoneNumberPresenter;
-    private final List<PhoneNumber> mPhoneNumbers;
-    private Contact mContact;
-
-    /**
-     * A presenter that presents the favorite state for phone number and provides the click
-     * listener.
-     */
-    public interface FavoritePhoneNumberPresenter {
-        /**
-         * Provides the click listener for the given phone number and its present view.
-         */
-        void onItemClicked(PhoneNumber phoneNumber, View itemView);
-    }
-
-    public FavoritePhoneNumberListAdapter(Context context,
-            FavoritePhoneNumberPresenter favoritePhoneNumberPresenter) {
-        mContext = context;
-        mFavoritePhoneNumberPresenter = favoritePhoneNumberPresenter;
-        mPhoneNumbers = new ArrayList<>();
-    }
-
-    /**
-     * Sets the phone numbers to display
-     */
-    public void setPhoneNumbers(Contact contact, List<PhoneNumber> phoneNumbers) {
-        mPhoneNumbers.clear();
-        mContact = contact;
-        mPhoneNumbers.addAll(phoneNumbers);
-
-        notifyDataSetChanged();
-    }
-
-    public Contact getContact() {
-        return mContact;
-    }
-
-    @Override
-    public int getCount() {
-        return mPhoneNumbers.size();
-    }
-
-    @Override
-    public PhoneNumber getItem(int position) {
-        return mPhoneNumbers.get(position);
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return position;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        View itemView;
-        if (convertView == null) {
-            itemView = LayoutInflater.from(mContext).inflate(
-                    R.layout.add_favorite_number_list_item, parent, false);
-        } else {
-            itemView = convertView;
-        }
-        PhoneNumber phoneNumber = getItem(position);
-        bind(phoneNumber, itemView);
-        return itemView;
-    }
-
-    void bind(PhoneNumber phoneNumber, View itemView) {
-        TextView phoneNumberView = itemView.findViewById(R.id.phone_number);
-        TextView phoneNumberDescriptionView = itemView.findViewById(R.id.phone_number_description);
-        phoneNumberView.setText(phoneNumber.getRawNumber());
-        CharSequence readableLabel = phoneNumber.getReadableLabel(itemView.getResources());
-
-        if (phoneNumber.isFavorite()) {
-            // This phone number is marked as favorite locally. Disable the favorite action button.
-            phoneNumberDescriptionView.setText(
-                    itemView.getResources().getString(R.string.local_favorite_number_description,
-                            readableLabel));
-            itemView.setActivated(true);
-            itemView.setEnabled(false);
-        } else if (mContact.isStarred()) {
-            // This contact is downloaded from phone, all phone numbers under this contact will show
-            // under the favorite tab. Disable the favorite action button.
-            phoneNumberDescriptionView.setText(
-                    itemView.getResources().getString(R.string.favorite_number_description,
-                            readableLabel));
-            itemView.setActivated(false);
-            itemView.setEnabled(false);
-        } else {
-            phoneNumberDescriptionView.setText(readableLabel);
-            itemView.setActivated(false);
-            itemView.setEnabled(true);
-            itemView.setOnClickListener(
-                    view -> mFavoritePhoneNumberPresenter.onItemClicked(phoneNumber, itemView));
-        }
-    }
-}
diff --git a/src/com/android/car/dialer/ui/common/PhoneNumberListAdapter.java b/src/com/android/car/dialer/ui/common/PhoneNumberListAdapter.java
deleted file mode 100644
index 923fb51..0000000
--- a/src/com/android/car/dialer/ui/common/PhoneNumberListAdapter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.dialer.ui.common;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.car.dialer.R;
-import com.android.car.telephony.common.PhoneNumber;
-
-import java.util.List;
-
-/**
- * {@link ArrayAdapter} that simply presents the {@link PhoneNumber} and its type as two line list
- * item.
- */
-public class PhoneNumberListAdapter extends ArrayAdapter<PhoneNumber> {
-    private final Context mContext;
-
-    public PhoneNumberListAdapter(Context context, List<PhoneNumber> phoneNumbers) {
-        super(context, R.layout.phone_number_list_item, R.id.phone_number, phoneNumbers);
-        mContext = context;
-    }
-
-    @Override
-    public View getView(int position, @Nullable View convertView,
-            @NonNull ViewGroup parent) {
-        View view = super.getView(position, convertView, parent);
-        PhoneNumber phoneNumber = getItem(position);
-        if (phoneNumber == null) {
-            return view;
-        }
-        TextView phoneNumberView = view.findViewById(R.id.phone_number);
-        phoneNumberView.setText(phoneNumber.getRawNumber());
-        TextView phoneNumberDescriptionView = view.findViewById(R.id.phone_number_description);
-        CharSequence readableLabel = phoneNumber.getReadableLabel(mContext.getResources());
-        if (phoneNumber.isPrimary()) {
-            phoneNumberDescriptionView.setText(
-                    mContext.getString(R.string.primary_number_description, readableLabel));
-        } else {
-            phoneNumberDescriptionView.setText(readableLabel);
-        }
-        return view;
-    }
-}
diff --git a/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java b/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java
index 6ddbad7..a45d5bc 100644
--- a/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java
+++ b/src/com/android/car/dialer/ui/favorite/AddFavoriteFragment.java
@@ -17,19 +17,24 @@
 package com.android.car.dialer.ui.favorite;
 
 import android.app.AlertDialog;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.widget.Toast;
 
 import androidx.lifecycle.ViewModelProviders;
 
 import com.android.car.dialer.R;
-import com.android.car.dialer.ui.common.FavoritePhoneNumberListAdapter;
 import com.android.car.dialer.ui.search.ContactResultsFragment;
 import com.android.car.telephony.common.Contact;
 import com.android.car.telephony.common.PhoneNumber;
 import com.android.car.ui.AlertDialogBuilder;
+import com.android.car.ui.recyclerview.CarUiContentListItem;
+import com.android.car.ui.recyclerview.CarUiListItem;
+import com.android.car.ui.recyclerview.CarUiListItemAdapter;
 
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -45,7 +50,12 @@
     }
 
     private AlertDialog mCurrentDialog;
-    private FavoritePhoneNumberListAdapter mDialogAdapter;
+    private CarUiListItemAdapter mDialogAdapter;
+    private List<CarUiListItem> mFavoritePhoneNumberList;
+    private Set<PhoneNumber> mSelectedNumbers;
+    private Contact mSelectedContact;
+    private Drawable mFavoriteIcon;
+    private Drawable mFavoriteIconEmpty;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -53,36 +63,77 @@
 
         FavoriteViewModel favoriteViewModel = ViewModelProviders.of(getActivity()).get(
                 FavoriteViewModel.class);
-        Set<PhoneNumber> selectedNumbers = new HashSet<>();
+        mSelectedNumbers = new HashSet<>();
 
-        mDialogAdapter = new FavoritePhoneNumberListAdapter(getContext(),
-                (phoneNumber, itemView) -> {
-                    boolean isActivated = itemView.isActivated();
-                    itemView.setActivated(!isActivated);
-                    if (isActivated) {
-                        selectedNumbers.remove(phoneNumber);
-                    } else {
-                        selectedNumbers.add(phoneNumber);
-                    }
-                }
-        );
+        mFavoriteIcon = getResources().getDrawable(R.drawable.ic_favorite_activatable, null);
+        mFavoriteIcon.setTintList(
+                getResources().getColorStateList(R.color.primary_icon_selector, null));
+
+        mFavoritePhoneNumberList = new ArrayList<>();
+        mDialogAdapter = new CarUiListItemAdapter(mFavoritePhoneNumberList);
 
         mCurrentDialog = new AlertDialogBuilder(getContext())
                 .setTitle(R.string.select_number_dialog_title)
-                .setAdapter(mDialogAdapter, null)
+                .setAdapter(mDialogAdapter)
                 .setNegativeButton(R.string.cancel_add_favorites_dialog, null)
                 .setPositiveButton(R.string.confirm_add_favorites_dialog,
                         (d, which) -> {
-                            for (PhoneNumber number : selectedNumbers) {
-                                favoriteViewModel.addToFavorite(mDialogAdapter.getContact(),
+                            for (PhoneNumber number : mSelectedNumbers) {
+                                favoriteViewModel.addToFavorite(mSelectedContact,
                                         number);
                             }
-                            selectedNumbers.clear();
+                            mSelectedNumbers.clear();
                             getFragmentManager().popBackStackImmediate();
                         })
                 .create();
     }
 
+    private void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
+        mFavoritePhoneNumberList.clear();
+        for (PhoneNumber number : phoneNumbers) {
+            CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
+            item.setTitle(number.getNumber());
+            item.setSupplementalIcon(mFavoriteIcon.getConstantState().newDrawable());
+            setFavoriteItemState(item, number);
+
+            item.setOnItemClickedListener((listItem) -> {
+                if (mSelectedNumbers.contains(number)) {
+                    mSelectedNumbers.remove(number);
+                    listItem.setActivated(false);
+                } else {
+                    mSelectedNumbers.add(number);
+                    listItem.setActivated(true);
+                }
+                mDialogAdapter.notifyItemChanged(mFavoritePhoneNumberList.indexOf(listItem));
+            });
+            mFavoritePhoneNumberList.add(item);
+        }
+        mDialogAdapter.notifyDataSetChanged();
+    }
+
+    private void setFavoriteItemState(CarUiContentListItem item, PhoneNumber number) {
+        CharSequence readableLabel = number.getReadableLabel(getResources());
+
+        if (number.isFavorite()) {
+            // This phone number is marked as favorite locally. Disable the favorite action button.
+            item.setEnabled(false);
+            item.setActivated(true);
+            item.setBody(getResources().getString(R.string.favorite_number_description,
+                    readableLabel));
+        } else if (mSelectedContact.isStarred()) {
+            // This contact is downloaded from phone, all phone numbers under this contact will show
+            // under the favorite tab. Disable the favorite action button.
+            item.setActivated(false);
+            item.setEnabled(false);
+            item.setBody(getResources().getString(R.string.favorite_number_description,
+                    readableLabel));
+        } else {
+            item.setEnabled(true);
+            item.setActivated(false);
+            item.setBody(readableLabel);
+        }
+    }
+
     @Override
     public void onShowContactDetail(Contact contact) {
         if (contact == null) {
@@ -90,11 +141,12 @@
             return;
         }
 
+        mSelectedContact = contact;
         if (contact.getNumbers().isEmpty()) {
             Toast.makeText(getContext(), R.string.no_phone_numbers, Toast.LENGTH_SHORT).show();
             mCurrentDialog.dismiss();
         } else {
-            mDialogAdapter.setPhoneNumbers(contact, contact.getNumbers());
+            setPhoneNumbers(contact.getNumbers());
             mCurrentDialog.show();
         }
     }