Merge "Add tests for CarUi class and add FPV to shared lib" into sc-dev
diff --git a/car-media-common/src/com/android/car/media/common/MediaButtonController.java b/car-media-common/src/com/android/car/media/common/MediaButtonController.java
index 1341507..1db7a31 100644
--- a/car-media-common/src/com/android/car/media/common/MediaButtonController.java
+++ b/car-media-common/src/com/android/car/media/common/MediaButtonController.java
@@ -88,6 +88,9 @@
                 R.id.circular_progress_bar);
         mPlayPauseStopImageView.setAction(PlayPauseStopImageView.ACTION_DISABLED);
         mPlayPauseStopImageView.setOnClickListener(this::onPlayPauseStopClicked);
+        // In non-touch mode, a browse list will request focus explicitly and its first element
+        // will get focused instead of this button
+        mPlayPauseStopImageView.setFocusedByDefault(true);
 
         mShowCircularProgressBar = context.getResources().getBoolean(
                 R.bool.show_circular_progress_bar);
diff --git a/car-telephony-common/src/com/android/car/telephony/common/Contact.java b/car-telephony-common/src/com/android/car/telephony/common/Contact.java
index 180ae6b..498e92b 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/Contact.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/Contact.java
@@ -32,7 +32,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 
 /**
  * Encapsulates data about a phone Contact entry. Typically loaded from the local Contact store.
@@ -201,21 +200,11 @@
 
     /**
      * All postal addresses of this contact mapping to the unique primary key for the raw data
-     * entry.
+     * entry
      */
     private final List<PostalAddress> mPostalAddresses = new ArrayList<>();
 
     /**
-     * Collator instance for proper comparison based on localized names.
-     */
-    private Collator mCollator;
-
-    /**
-     * Locale used for mCollator creation.
-     */
-    private Locale mLocale;
-
-    /**
      * Parses a contact entry for a Cursor loaded from the Contact Database. A new contact will be
      * created and returned.
      */
@@ -639,7 +628,7 @@
         for (int i = 0; i < phoneNumberListLength; i++) {
             PhoneNumber phoneNumber = source.readParcelable(PhoneNumber.class.getClassLoader());
             contact.mPhoneNumbers.add(phoneNumber);
-            if (phoneNumber != null && phoneNumber.isPrimary()) {
+            if (phoneNumber.isPrimary()) {
                 contact.mPrimaryPhoneNumber = phoneNumber;
             }
         }
@@ -687,12 +676,8 @@
         if (type != otherType) {
             return Integer.compare(type, otherType);
         }
-        Locale currentLocale = Locale.getDefault();
-        if (mCollator == null || mLocale.equals(currentLocale)) {
-            mCollator = Collator.getInstance(currentLocale);
-            mLocale = currentLocale;
-        }
-        return mCollator.compare(name == null ? "" : name, otherName == null ? "" : otherName);
+        Collator collator = Collator.getInstance();
+        return collator.compare(name == null ? "" : name, otherName == null ? "" : otherName);
     }
 
     /**
diff --git a/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java b/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java
index 8091f42..572dc8a 100644
--- a/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java
+++ b/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java
@@ -43,14 +43,7 @@
 public class ContactTest {
 
     private static final int DISPLAY_NAME_COLUMN = 1;
-    private static final int MIMETYPE_COLUMN = 2;
-    private static final int LOOK_UP_KEY_COLUMN = 3;
-    private static final int PRIMARY_KEY_COLUMN = 4;
-    private static final String PHONEBOOK_LABEL = "phonebook_label";
-    private static final int PHONEBOOK_LABEL_COLUMN = 5;
 
-    private static final String EMPTY_MIME = "";
-    private static final String DEFAULT_LOOK_UP_KEY = "PRIMARY";
     private static final String NULL_NAME = null;
     private static final String EMPTY_NAME = "";
     private static final String LETTER_NAME_1 = "test";
@@ -86,124 +79,94 @@
 
         when(mMockCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)).thenReturn(
                 DISPLAY_NAME_COLUMN);
-        when(mMockCursor.getColumnIndex(ContactsContract.RawContacts.SORT_KEY_PRIMARY)).thenReturn(
-                PRIMARY_KEY_COLUMN);
-        when(mMockCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).thenReturn(
-                MIMETYPE_COLUMN);
-        when(mMockCursor.getString(MIMETYPE_COLUMN)).thenReturn(EMPTY_MIME);
-        when(mMockCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY)).thenReturn(
-                LOOK_UP_KEY_COLUMN);
-        when(mMockCursor.getString(LOOK_UP_KEY_COLUMN)).thenReturn(DEFAULT_LOOK_UP_KEY);
-        when(mMockCursor.getColumnIndex(PHONEBOOK_LABEL)).thenReturn(
-                PHONEBOOK_LABEL_COLUMN);
-
         when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(
                 mMockTelephonyManager);
         when(mMockTelephonyManager.getSimCountryIso()).thenReturn("");
 
-        when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("");
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(NULL_NAME);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(NULL_NAME);
         mNullName = Contact.fromCursor(mMockContext, mMockCursor);
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(EMPTY_NAME);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(EMPTY_NAME);
         mEmptyName = Contact.fromCursor(mMockContext, mMockCursor);
-
-        when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("T");
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(LETTER_NAME_1);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(LETTER_NAME_1);
         mLetterName1 = Contact.fromCursor(mMockContext, mMockCursor);
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(LETTER_NAME_2);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(LETTER_NAME_2);
         mLetterName2 = Contact.fromCursor(mMockContext, mMockCursor);
-
-        when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("#");
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(DIGIT_NAME_1);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(DIGIT_NAME_1);
         mDigitName1 = Contact.fromCursor(mMockContext, mMockCursor);
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(DIGIT_NAME_2);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(DIGIT_NAME_2);
         mDigitName2 = Contact.fromCursor(mMockContext, mMockCursor);
-
-        when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("");
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(SPEC_CHAR_NAME);
+        when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(SPEC_CHAR_NAME);
         mSpecCharName = Contact.fromCursor(mMockContext, mMockCursor);
     }
 
     @Test
     public void compareTo_TwoNullStrings_Equal() {
-        // NULL == NULL
         int compareResult = mNullName.compareTo(mNullName);
         assertEquals(COMPARE_RESULT_EQUAL, compareResult);
     }
 
     @Test
     public void compareTo_TwoEmptyStrings_Equal() {
-        // "" == NULL
         int compareResult = mEmptyName.compareTo(mEmptyName);
         assertEquals(COMPARE_RESULT_EQUAL, compareResult);
     }
 
     @Test
     public void compareTo_TwoLetterStrings_Larger() {
-        // "test" > "ta"
         int compareResult = mLetterName1.compareTo(mLetterName2);
         assertEquals(COMPARE_RESULT_LARGER, compareResult);
     }
 
     @Test
     public void compareTo_TwoDigitStrings_Smaller() {
-        // "123" < "321"
         int compareResult = mDigitName1.compareTo(mDigitName2);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_LetterAndDigitStrings_Smaller() {
-        // "test" < "123", because of Phonebook_label
         int compareResult = mLetterName1.compareTo(mDigitName1);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_LetterAndSpecialCharStrings_Smaller() {
-        // "test" <"-", because of Phonebook_label
         int compareResult = mLetterName1.compareTo(mSpecCharName);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_LetterAndEmptyStrings_Smaller() {
-        // "test" < "", because of Phonebook_label
         int compareResult = mLetterName1.compareTo(mEmptyName);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_LetterAndNullStrings_Smaller() {
-        // "test < NULL, because of Phonebook_label
         int compareResult = mLetterName1.compareTo(mNullName);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_DigitAndSpecialCharStrings_Smaller() {
-        // "123" < "-", because of Phonebook_label
         int compareResult = mDigitName1.compareTo(mSpecCharName);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_DigitAndEmptyStrings_Smaller() {
-        // "123" > "", because of Phonebook_label
         int compareResult = mDigitName1.compareTo(mEmptyName);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_DigitAndNullStrings_Smaller() {
-        // "123" < NULL, because of Phonebook_label
         int compareResult = mDigitName1.compareTo(mNullName);
         assertEquals(COMPARE_RESULT_SMALLER, compareResult);
     }
 
     @Test
     public void compareTo_SpecialCharAndEmptyStrings_Any() {
-        // "-" > ""
         int compareResult = mSpecCharName.compareTo(mEmptyName);
         assertThat(compareResult).isAnyOf(COMPARE_RESULT_SMALLER, COMPARE_RESULT_EQUAL,
                 COMPARE_RESULT_LARGER);
@@ -211,7 +174,6 @@
 
     @Test
     public void compareTo_SpecialCharAndNullStrings_Any() {
-        // "-" > NULL
         int compareResult = mSpecCharName.compareTo(mNullName);
         assertThat(compareResult).isAnyOf(COMPARE_RESULT_SMALLER, COMPARE_RESULT_EQUAL,
                 COMPARE_RESULT_LARGER);
@@ -219,97 +181,24 @@
 
     @Test
     public void compareTo_EmptyAndNullStrings_Equal() {
-        // "" == NULL
         int compareResult = mEmptyName.compareTo(mNullName);
         assertEquals(COMPARE_RESULT_EQUAL, compareResult);
     }
 
     @Test
     public void sortContactTest() {
-        List<Contact> expectedList = new ArrayList<>();
-        expectedList.add(mLetterName2);
-        expectedList.add(mLetterName1);
-        expectedList.add(mDigitName1);
-        expectedList.add(mDigitName2);
-        expectedList.add(mEmptyName);
-        expectedList.add(mSpecCharName);
-
+        List<Contact> sortResultList = new ArrayList<>();
+        sortResultList.add(mLetterName2);
+        sortResultList.add(mLetterName1);
+        sortResultList.add(mDigitName1);
+        sortResultList.add(mDigitName2);
+        sortResultList.add(mEmptyName);
+        sortResultList.add(mSpecCharName);
         List<Contact> contactList = new ArrayList<>();
-        contactList.add(mDigitName1);
-        contactList.add(mSpecCharName);
-        contactList.add(mLetterName1);
-        contactList.add(mEmptyName);
-        contactList.add(mLetterName2);
-        contactList.add(mDigitName2);
+        contactList.addAll(sortResultList);
 
+        Collections.shuffle(contactList);
         Collections.sort(contactList);
-        assertArrayEquals(expectedList.toArray(), contactList.toArray());
-    }
-
-    @Test
-    public void sortContactPrimaryTest() {
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn("tä");
-        Contact letterName3 = Contact.fromCursor(mMockContext, mMockCursor);
-
-        when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn("tb");
-        Contact letterName4 = Contact.fromCursor(mMockContext, mMockCursor);
-
-        List<Contact> expectedList = new ArrayList<>();
-        expectedList.add(mLetterName2);
-        expectedList.add(letterName3);
-        expectedList.add(letterName4);
-        expectedList.add(mLetterName1);
-        expectedList.add(mDigitName1);
-        expectedList.add(mDigitName2);
-        expectedList.add(mEmptyName);
-        expectedList.add(mSpecCharName);
-
-        List<Contact> contactList = new ArrayList<>();
-        contactList.add(mDigitName1);
-        contactList.add(letterName4);
-        contactList.add(mSpecCharName);
-        contactList.add(mLetterName1);
-        contactList.add(mEmptyName);
-        contactList.add(mLetterName2);
-        contactList.add(letterName3);
-        contactList.add(mDigitName2);
-
-        Collections.sort(contactList, (o1, o2) -> o1.compareBySortKeyPrimary(o2));
-        assertArrayEquals(expectedList.toArray(), contactList.toArray());
-    }
-
-    @Test
-    public void sortContactAlternativeTest() {
-        int alternativeColumnIndex = 20;
-        when(mMockCursor.getColumnIndex(ContactsContract.RawContacts.SORT_KEY_ALTERNATIVE))
-                .thenReturn(alternativeColumnIndex);
-        when(mMockCursor.getString(alternativeColumnIndex)).thenReturn("tä");
-        Contact letterName3 = Contact.fromCursor(mMockContext, mMockCursor);
-
-        when(mMockCursor.getString(alternativeColumnIndex)).thenReturn("tb");
-        Contact letterName4 = Contact.fromCursor(mMockContext, mMockCursor);
-
-        List<Contact> expectedList = new ArrayList<>();
-        expectedList.add(mLetterName2);
-        expectedList.add(letterName3);
-        expectedList.add(letterName4);
-        expectedList.add(mLetterName1);
-        expectedList.add(mDigitName1);
-        expectedList.add(mDigitName2);
-        expectedList.add(mEmptyName);
-        expectedList.add(mSpecCharName);
-
-        List<Contact> contactList = new ArrayList<>();
-        contactList.add(mDigitName1);
-        contactList.add(letterName4);
-        contactList.add(mSpecCharName);
-        contactList.add(mLetterName1);
-        contactList.add(mEmptyName);
-        contactList.add(mLetterName2);
-        contactList.add(letterName3);
-        contactList.add(mDigitName2);
-
-        Collections.sort(contactList, (o1, o2) -> o1.compareBySortKeyAlt(o2));
-        assertArrayEquals(expectedList.toArray(), contactList.toArray());
+        assertArrayEquals(sortResultList.toArray(), contactList.toArray());
     }
 }
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/appstyledview/AppStyledViewControllerImpl.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/appstyledview/AppStyledViewControllerImpl.java
index 41b6a40..50ded45 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/appstyledview/AppStyledViewControllerImpl.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/appstyledview/AppStyledViewControllerImpl.java
@@ -25,6 +25,7 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 
 import androidx.recyclerview.widget.LinearLayoutManager;
@@ -132,8 +133,10 @@
             close.setImageResource(R.drawable.car_ui_icon_close);
         }
 
-        if (mAppStyledVCloseClickListener != null) {
-            close.setOnClickListener((v) -> {
+        FrameLayout navContainer =
+                appStyleView.findViewById(R.id.car_ui_app_styled_view_nav_icon_container);
+        if (mAppStyledVCloseClickListener != null && navContainer != null) {
+            navContainer.setOnClickListener((v) -> {
                 mAppStyledVCloseClickListener.onClick();
             });
         }
diff --git a/car-ui-lib/car-ui-lib/src/main/res-private/drawable/car_ui_app_styled_view_ripple.xml b/car-ui-lib/car-ui-lib/src/main/res-private/drawable/car_ui_app_styled_view_ripple.xml
new file mode 100644
index 0000000..fadd180
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/main/res-private/drawable/car_ui_app_styled_view_ripple.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~
+  ~ Copyright (C) 2021 Google Inc.
+  ~
+  ~ 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:state_focused="true" android:state_pressed="true">
+    <shape android:shape="oval">
+      <solid android:color="#8A94CBFF"/>
+      <stroke android:width="4dp"
+          android:color="#94CBFF"/>
+      <size android:width="48dp"
+          android:height="48dp"/>
+    </shape>
+  </item>
+  <item android:state_focused="true">
+    <shape android:shape="oval">
+      <solid android:color="#3D94CBFF"/>
+      <stroke android:width="8dp"
+          android:color="#94CBFF"/>
+      <size android:width="48dp"
+          android:height="48dp"/>
+    </shape>
+  </item>
+  <item>
+    <ripple android:color="#27ffffff">
+      <item android:id="@android:id/mask">
+        <shape android:shape="oval">
+          <solid android:color="#FFFFFF"/>
+        </shape>
+      </item>
+    </ripple>
+  </item>
+</selector>
diff --git a/car-ui-lib/car-ui-lib/src/main/res-private/layout-land/car_ui_app_styled_view.xml b/car-ui-lib/car-ui-lib/src/main/res-private/layout-land/car_ui_app_styled_view.xml
index 880c996..47daee0 100644
--- a/car-ui-lib/car-ui-lib/src/main/res-private/layout-land/car_ui_app_styled_view.xml
+++ b/car-ui-lib/car-ui-lib/src/main/res-private/layout-land/car_ui_app_styled_view.xml
@@ -32,23 +32,23 @@
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintRight_toLeftOf="@+id/car_ui_app_styled_content"
-        style="@style/Widget.CarUi.Toolbar.Container">
+        app:layout_constraintRight_toLeftOf="@+id/car_ui_app_styled_content">
         <FrameLayout
             android:id="@+id/car_ui_app_styled_view_nav_icon_container"
+            android:layout_marginVertical="10dp"
+            android:layout_marginHorizontal="18dp"
             android:layout_width="76dp"
             android:layout_height="76dp"
             android:layout_gravity="center"
             app:layout_constraintHorizontal_bias="0.0"
-            style="@style/Widget.CarUi.Toolbar.NavIconContainer">
+            android:background="@drawable/car_ui_app_styled_view_ripple">
             <ImageView
                 android:id="@+id/car_ui_app_styled_view_icon_close"
                 android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
                 android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
                 android:tint="@color/car_ui_toolbar_nav_icon_color"
                 android:layout_gravity="center"
-                android:scaleType="fitXY"
-                style="@style/Widget.CarUi.Toolbar.NavIcon"/>
+                android:scaleType="fitXY"/>
         </FrameLayout>
     </com.android.car.ui.FocusArea>
     <com.android.car.ui.recyclerview.CarUiRecyclerView
diff --git a/car-ui-lib/car-ui-lib/src/main/res-private/layout/car_ui_app_styled_view.xml b/car-ui-lib/car-ui-lib/src/main/res-private/layout/car_ui_app_styled_view.xml
index d26b8e2..f544e1d 100644
--- a/car-ui-lib/car-ui-lib/src/main/res-private/layout/car_ui_app_styled_view.xml
+++ b/car-ui-lib/car-ui-lib/src/main/res-private/layout/car_ui_app_styled_view.xml
@@ -34,22 +34,22 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/car_ui_toolbar_first_row_height"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        style="@style/Widget.CarUi.Toolbar.Container">
+        app:layout_constraintStart_toStartOf="parent">
         <FrameLayout
             android:id="@+id/car_ui_app_styled_view_nav_icon_container"
+            android:layout_marginVertical="10dp"
+            android:layout_marginHorizontal="18dp"
+            android:background="@drawable/car_ui_app_styled_view_ripple"
             android:layout_width="@dimen/car_ui_toolbar_margin"
             android:layout_height="match_parent"
-            app:layout_constraintHorizontal_bias="0.0"
-            style="@style/Widget.CarUi.Toolbar.NavIconContainer">
+            app:layout_constraintHorizontal_bias="0.0">
             <ImageView
                 android:id="@+id/car_ui_app_styled_view_icon_close"
                 android:layout_width="@dimen/car_ui_toolbar_nav_icon_size"
                 android:layout_height="@dimen/car_ui_toolbar_nav_icon_size"
                 android:tint="@color/car_ui_toolbar_nav_icon_color"
                 android:layout_gravity="center"
-                android:scaleType="fitXY"
-                style="@style/Widget.CarUi.Toolbar.NavIcon"/>
+                android:scaleType="fitXY"/>
         </FrameLayout>
     </com.android.car.ui.FocusArea>
     <com.android.car.ui.recyclerview.CarUiRecyclerView