Merge "Fix missing gear icon on "More" toolbar button" into pi-car-dev
diff --git a/res/layout/settings_fragment.xml b/res/layout/settings_fragment.xml
index e4628de..9dfbd90 100644
--- a/res/layout/settings_fragment.xml
+++ b/res/layout/settings_fragment.xml
@@ -27,7 +27,7 @@
         android:id="@android:id/list_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
-        <com.android.car.apps.common.widget.PagedRecyclerView
+        <com.android.car.ui.recyclerview.CarUiRecyclerView
             android:id="@+id/recycler_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
diff --git a/res/xml/modify_system_settings_fragment.xml b/res/xml/modify_system_settings_fragment.xml
index 7aa22b4..a9bb722 100644
--- a/res/xml/modify_system_settings_fragment.xml
+++ b/res/xml/modify_system_settings_fragment.xml
@@ -19,10 +19,11 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/modify_system_settings_title">
-    <Preference
+    <com.android.car.ui.preference.CarUiPreference
         android:key="@string/pk_modify_system_settings_description"
         android:selectable="false"
-        android:summary="@string/modify_system_settings_description"/>
+        android:summary="@string/modify_system_settings_description"
+        settings:showChevron="false"/>
     <com.android.car.settings.common.LogicalPreferenceGroup
         android:key="@string/pk_modify_system_settings"
         settings:controller="com.android.car.settings.applications.specialaccess.AppOpsPreferenceController"/>
diff --git a/src/com/android/car/settings/accounts/AccountListPreferenceController.java b/src/com/android/car/settings/accounts/AccountListPreferenceController.java
index 8075558..2007aca 100644
--- a/src/com/android/car/settings/accounts/AccountListPreferenceController.java
+++ b/src/com/android/car/settings/accounts/AccountListPreferenceController.java
@@ -251,7 +251,7 @@
         return false;
     }
 
-    private static class AccountPreference extends Preference {
+    private static class AccountPreference extends CarUiPreference {
         /** Account that this Preference represents. */
         private final Account mAccount;
         private final CharSequence mLabel;
@@ -266,6 +266,7 @@
             setTitle(account.name);
             setSummary(label);
             setIcon(icon);
+            setShowChevron(false);
         }
 
         /**
diff --git a/src/com/android/car/settings/accounts/ChooseAccountPreferenceController.java b/src/com/android/car/settings/accounts/ChooseAccountPreferenceController.java
index d1cbafa..540edab 100644
--- a/src/com/android/car/settings/accounts/ChooseAccountPreferenceController.java
+++ b/src/com/android/car/settings/accounts/ChooseAccountPreferenceController.java
@@ -29,11 +29,11 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.collection.ArrayMap;
-import androidx.preference.Preference;
 import androidx.preference.PreferenceGroup;
 
 import com.android.car.settings.common.FragmentController;
 import com.android.car.settings.common.PreferenceController;
+import com.android.car.ui.preference.CarUiPreference;
 import com.android.settingslib.accounts.AuthenticatorHelper;
 
 import java.util.ArrayList;
@@ -251,7 +251,7 @@
         void addAccount(String accountType);
     }
 
-    private static class AuthenticatorDescriptionPreference extends Preference {
+    private static class AuthenticatorDescriptionPreference extends CarUiPreference {
         private final String mType;
 
         AuthenticatorDescriptionPreference(Context context, String accountType, CharSequence label,
@@ -262,6 +262,7 @@
             setKey(accountType);
             setTitle(label);
             setIcon(icon);
+            setShowChevron(false);
         }
 
         private String getAccountType() {
diff --git a/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceController.java b/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceController.java
index f61a16f..60bffa8 100644
--- a/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceController.java
+++ b/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceController.java
@@ -19,7 +19,6 @@
 import android.car.drivingstate.CarUxRestrictions;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 
 import androidx.annotation.Nullable;
 
@@ -48,27 +47,22 @@
     protected void updateState(ButtonPreference preference) {
         super.updateState(preference);
 
+        // If activity does not exist, return. Otherwise allow intenting to the activity.
         Intent intent = getSettingIntent(getCurrentDefaultAppInfo());
-        boolean isSafeIntent = false;
-        if (intent != null) {
-            ActivityInfo info = intent.resolveActivityInfo(
-                    getContext().getPackageManager(), intent.getFlags());
-            // If activity exists and is visible to Car Settings, allow intenting to the activity.
-            if (info != null && info.exported) {
-                isSafeIntent = true;
-            }
+        if (intent == null || intent.resolveActivityInfo(
+                getContext().getPackageManager(), intent.getFlags()) == null) {
+            preference.showAction(false);
+            return;
         }
-        preference.showAction(isSafeIntent);
-        if (isSafeIntent) {
-            // Use startActivityForResult because some apps need to check the identity of the
-            // caller.
-            preference.setOnButtonClickListener(p -> getContext().startActivityForResult(
-                    getContext().getBasePackageName(),
-                    intent,
-                    /* requestCode= */ 0,
-                    /* options= */ null
-            ));
-        }
+
+        // Use startActivityForResult because some apps need to check the identity of the caller.
+        preference.setOnButtonClickListener(p -> getContext().startActivityForResult(
+                getContext().getBasePackageName(),
+                intent,
+                /* requestCode= */ 0,
+                /* options= */ null
+        ));
+        preference.showAction(true);
     }
 
     /**
diff --git a/src/com/android/car/settings/common/BaseFragment.java b/src/com/android/car/settings/common/BaseFragment.java
index 6055954..17b957e 100644
--- a/src/com/android/car/settings/common/BaseFragment.java
+++ b/src/com/android/car/settings/common/BaseFragment.java
@@ -23,7 +23,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.TextView;
 
 import androidx.annotation.LayoutRes;
 import androidx.annotation.NonNull;
@@ -78,8 +77,8 @@
 
     /**
      * Returns the string id for the current Fragment title. Subclasses should override this
-     * method to set the title to display. Use {@link #setTitle(CharSequence)} to update the
-     * displayed title while resumed. The default title is the Settings Activity label.
+     * method to set the title to display. Use {@link #getToolbar().setTitle(CharSequence)} to
+     * update the displayed title while resumed. The default title is the Settings Activity label.
      */
     @StringRes
     protected int getTitleId() {
@@ -106,19 +105,6 @@
         return requireActivity().findViewById(R.id.toolbar);
     }
 
-    /**
-     * Should be used to override fragment's title. This should only be called after
-     * {@link #onActivityCreated(Bundle)}.
-     *
-     * @param title CharSequence to set as the new title.
-     */
-    protected final void setTitle(CharSequence title) {
-        TextView titleView = requireActivity().findViewById(R.id.title);
-        if (titleView != null) {
-            titleView.setText(title);
-        }
-    }
-
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
diff --git a/src/com/android/car/settings/common/SettingsFragment.java b/src/com/android/car/settings/common/SettingsFragment.java
index e4e7e5b..82f0f6a 100644
--- a/src/com/android/car/settings/common/SettingsFragment.java
+++ b/src/com/android/car/settings/common/SettingsFragment.java
@@ -36,14 +36,10 @@
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.lifecycle.Lifecycle;
-import androidx.preference.EditTextPreference;
-import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
 import com.android.car.settings.R;
-import com.android.car.ui.preference.EditTextPreferenceDialogFragment;
-import com.android.car.ui.preference.ListPreferenceDialogFragment;
 import com.android.car.ui.preference.PreferenceFragment;
 import com.android.car.ui.toolbar.MenuItem;
 import com.android.car.ui.toolbar.Toolbar;
@@ -90,7 +86,7 @@
     protected abstract int getPreferenceScreenResId();
 
     protected Toolbar getToolbar() {
-        return requireActivity().requireViewById(R.id.toolbar);
+        return requireActivity().findViewById(R.id.toolbar);
     }
     /**
      * Returns the MenuItems to display in the toolbar. Subclasses should override this to
@@ -254,27 +250,16 @@
             return;
         }
 
-        DialogFragment dialogFragment;
         if (preference instanceof ValidatedEditTextPreference) {
-            if (preference instanceof PasswordEditTextPreference) {
-                dialogFragment = PasswordEditTextPreferenceDialogFragment.newInstance(
-                        preference.getKey());
-            } else {
-                dialogFragment = ValidatedEditTextPreferenceDialogFragment.newInstance(
-                        preference.getKey());
-            }
-        } else if (preference instanceof EditTextPreference) {
-            dialogFragment = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
-        } else if (preference instanceof ListPreference) {
-            dialogFragment = ListPreferenceDialogFragment.newInstance(preference.getKey());
-        } else {
-            throw new IllegalArgumentException(
-                    "Tried to display dialog for unknown preference type. Did you forget to "
-                            + "override onDisplayPreferenceDialog()?");
-        }
+            DialogFragment dialogFragment = preference instanceof PasswordEditTextPreference
+                    ? PasswordEditTextPreferenceDialogFragment.newInstance(preference.getKey())
+                    : ValidatedEditTextPreferenceDialogFragment.newInstance(preference.getKey());
 
-        dialogFragment.setTargetFragment(/* fragment= */ this, /* requestCode= */ 0);
-        showDialog(dialogFragment, DIALOG_FRAGMENT_TAG);
+            dialogFragment.setTargetFragment(/* fragment= */ this, /* requestCode= */ 0);
+            showDialog(dialogFragment, DIALOG_FRAGMENT_TAG);
+        } else {
+            super.onDisplayPreferenceDialog(preference);
+        }
     }
 
     @Override
diff --git a/src/com/android/car/settings/language/ChildLocalePickerFragment.java b/src/com/android/car/settings/language/ChildLocalePickerFragment.java
index b5fc5ba..aa6c1b2 100644
--- a/src/com/android/car/settings/language/ChildLocalePickerFragment.java
+++ b/src/com/android/car/settings/language/ChildLocalePickerFragment.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.os.Bundle;
-import android.widget.TextView;
 
 import androidx.annotation.XmlRes;
 
@@ -70,8 +69,7 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        TextView titleView = getActivity().findViewById(R.id.title);
-        titleView.setText(mParentLocaleInfo.getFullNameNative());
+        getToolbar().setTitle(mParentLocaleInfo.getFullNameNative());
     }
 
     @Override
diff --git a/src/com/android/car/settings/system/MasterClearFragment.java b/src/com/android/car/settings/system/MasterClearFragment.java
index e6deb06..91ee7ae 100644
--- a/src/com/android/car/settings/system/MasterClearFragment.java
+++ b/src/com/android/car/settings/system/MasterClearFragment.java
@@ -28,11 +28,11 @@
 import androidx.annotation.XmlRes;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.car.apps.common.widget.PagedRecyclerView;
 import com.android.car.settings.R;
 import com.android.car.settings.common.ActivityResultCallback;
 import com.android.car.settings.common.SettingsFragment;
 import com.android.car.settings.security.CheckLockActivity;
+import com.android.car.ui.recyclerview.CarUiRecyclerView;
 import com.android.car.ui.toolbar.MenuItem;
 
 import java.util.Collections;
@@ -85,8 +85,8 @@
                 new ViewTreeObserver.OnGlobalLayoutListener() {
                     @Override
                     public void onGlobalLayout() {
-                        if (recyclerView instanceof PagedRecyclerView) {
-                            PagedRecyclerView pagedRecyclerView = (PagedRecyclerView) recyclerView;
+                        if (recyclerView instanceof CarUiRecyclerView) {
+                            CarUiRecyclerView pagedRecyclerView = (CarUiRecyclerView) recyclerView;
                             if (!pagedRecyclerView.fullyInitialized()) {
                                 return;
                             }
@@ -112,8 +112,8 @@
     /** Returns {@code true} if the RecyclerView is completely displaying the last item. */
     private boolean isAtEnd() {
         RecyclerView recyclerView = getListView();
-        RecyclerView.LayoutManager layoutManager = (recyclerView instanceof PagedRecyclerView)
-                ? ((PagedRecyclerView) recyclerView).getEffectiveLayoutManager()
+        RecyclerView.LayoutManager layoutManager = (recyclerView instanceof CarUiRecyclerView)
+                ? ((CarUiRecyclerView) recyclerView).getEffectiveLayoutManager()
                 : recyclerView.getLayoutManager();
         if (layoutManager == null || layoutManager.getChildCount() == 0) {
             return true;
diff --git a/tests/robotests/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceControllerTest.java
index 55179a7..73db10b 100644
--- a/tests/robotests/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/car/settings/applications/defaultapps/DefaultAppsPickerEntryBasePreferenceControllerTest.java
@@ -121,7 +121,7 @@
     }
 
     @Test
-    public void refreshUi_hasSettingIntentButNoVisibleActivity_actionButtonIsNotVisible() {
+    public void refreshUi_hasSettingIntentButNoVisibleActivity_actionButtonIsVisible() {
         ActivityInfo activityInfo = new ActivityInfo();
         activityInfo.exported = false;
         ResolveInfo resolveInfo = new ResolveInfo();
@@ -132,7 +132,7 @@
         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
         mController.refreshUi();
 
-        assertThat(mButtonPreference.isActionShown()).isFalse();
+        assertThat(mButtonPreference.isActionShown()).isTrue();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/car/settings/common/SettingsFragmentTest.java b/tests/robotests/src/com/android/car/settings/common/SettingsFragmentTest.java
index 7710c95..64477ba 100644
--- a/tests/robotests/src/com/android/car/settings/common/SettingsFragmentTest.java
+++ b/tests/robotests/src/com/android/car/settings/common/SettingsFragmentTest.java
@@ -38,8 +38,6 @@
 import com.android.car.settings.R;
 import com.android.car.settings.testutils.DummyFragment;
 import com.android.car.settings.testutils.FragmentController;
-import com.android.car.ui.preference.EditTextPreferenceDialogFragment;
-import com.android.car.ui.preference.ListPreferenceDialogFragment;
 import com.android.car.ui.toolbar.Toolbar;
 
 import org.junit.Before;
@@ -93,30 +91,6 @@
     }
 
     @Test
-    public void onDisplayPreferenceDialog_editTextPreference_showsDialog() {
-        mFragmentController.setup();
-
-        mFragment.getPreferenceScreen().findPreference(
-                mContext.getString(R.string.tpk_edit_text_preference)).performClick();
-
-        assertThat(mFragment.getFragmentManager().findFragmentByTag(
-                SettingsFragment.DIALOG_FRAGMENT_TAG)).isInstanceOf(
-                EditTextPreferenceDialogFragment.class);
-    }
-
-    @Test
-    public void onDisplayPreferenceDialog_listPreference_showsDialog() {
-        mFragmentController.setup();
-
-        mFragment.getPreferenceScreen().findPreference(
-                mContext.getString(R.string.tpk_list_preference)).performClick();
-
-        assertThat(mFragment.getFragmentManager().findFragmentByTag(
-                SettingsFragment.DIALOG_FRAGMENT_TAG)).isInstanceOf(
-                ListPreferenceDialogFragment.class);
-    }
-
-    @Test
     public void onDisplayPreferenceDialog_unknownPreferenceType_throwsIllegalArgumentException() {
         mFragmentController.setup();
 
@@ -125,27 +99,6 @@
     }
 
     @Test
-    public void onDisplayPreferenceDialog_alreadyShowing_doesNothing() {
-        mFragmentController.setup();
-
-        // Show a dialog.
-        mFragment.getPreferenceScreen().findPreference(
-                mContext.getString(R.string.tpk_edit_text_preference)).performClick();
-        assertThat(mFragment.getFragmentManager().findFragmentByTag(
-                SettingsFragment.DIALOG_FRAGMENT_TAG)).isInstanceOf(
-                EditTextPreferenceDialogFragment.class);
-
-        // Attempt to show another.
-        mFragment.getPreferenceScreen().findPreference(
-                mContext.getString(R.string.tpk_list_preference)).performClick();
-
-        // Assert only one shown at a time.
-        assertThat(mFragment.getFragmentManager().findFragmentByTag(
-                SettingsFragment.DIALOG_FRAGMENT_TAG)).isInstanceOf(
-                EditTextPreferenceDialogFragment.class);
-    }
-
-    @Test
     public void launchFragment_otherFragment_opensFragment() {
         mFragmentController.setup();
         TestSettingsFragment otherFragment = new TestSettingsFragment();
diff --git a/tests/robotests/src/com/android/car/settings/system/MasterClearFragmentTest.java b/tests/robotests/src/com/android/car/settings/system/MasterClearFragmentTest.java
index 4bc6fca..f59dfb8 100644
--- a/tests/robotests/src/com/android/car/settings/system/MasterClearFragmentTest.java
+++ b/tests/robotests/src/com/android/car/settings/system/MasterClearFragmentTest.java
@@ -92,7 +92,9 @@
 
     @Test
     public void masterClearButtonClicked_launchesCheckLockActivity() {
-        findMasterClearButton(mFragment.requireActivity()).performClick();
+        MenuItem masterClearButton = findMasterClearButton(mFragment.requireActivity());
+        masterClearButton.setEnabled(true);
+        masterClearButton.performClick();
 
         Intent startedIntent = ShadowApplication.getInstance().getNextStartedActivity();
         assertThat(startedIntent.getComponent().getClassName()).isEqualTo(