Merge "Move "About Phone" to bottom of Settings main IA, above "Tips & Support""
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9980406..98adebb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2962,16 +2962,6 @@
                        android:value="true" />
         </activity>
 
-        <activity android:name="Settings$DirectoryAccessSettingsActivity"
-                android:label="@string/directory_access">
-            <intent-filter>
-                <action android:name="android.settings.STORAGE_VOLUME_ACCESS_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.applications.manageapplications.ManageApplications" />
-        </activity>
-
         <provider android:name=".slices.SettingsSliceProvider"
                   android:authorities="com.android.settings.slices;android.settings.slices"
                   android:exported="true"
diff --git a/libs/contextualcards.aar b/libs/contextualcards.aar
index 5e855fa..892a6be 100755
--- a/libs/contextualcards.aar
+++ b/libs/contextualcards.aar
Binary files differ
diff --git a/protos/contextual_card_list.proto b/protos/contextual_card_list.proto
index 89e6c13..ea82408 100644
--- a/protos/contextual_card_list.proto
+++ b/protos/contextual_card_list.proto
@@ -8,12 +8,24 @@
 }
 
 message ContextualCard {
-  // Slice uri of the contextual card
+
+  /**
+   * The category of a card: this is a hint for how a card should be collected,
+   * ranked, and presented
+   */
+  enum Category {
+    DEFAULT = 0;
+    SUGGESTION = 1;
+    POSSIBLE = 2;
+    IMPORTANT = 3;
+    EXCLUSIVE = 4;
+  }
+
+  /** Slice uri of the contextual card */
   optional string sliceUri = 1;
 
-  // {@link ContextualCardCategory}.
-  optional int32 category = 2;
-
-  // Name of the card. It should be identical in every app
+  /** Name of the card. It should be identical in every app */
   optional string cardName = 3;
-}
\ No newline at end of file
+
+  optional Category card_category = 4;
+}
diff --git a/res/layout/homepage_condition_full_tile.xml b/res/layout/homepage_condition_full_tile.xml
new file mode 100644
index 0000000..f00132b
--- /dev/null
+++ b/res/layout/homepage_condition_full_tile.xml
@@ -0,0 +1,78 @@
+<?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.cardview.widget.CardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    style="@style/ContextualCardStyle">
+
+    <LinearLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/homepage_condition_full_card_height"
+        android:paddingStart="@dimen/homepage_card_padding_start"
+        android:paddingEnd="@dimen/homepage_card_padding_end"
+        android:orientation="horizontal"
+        android:gravity="center_vertical">
+
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/suggestion_card_icon_size"
+            android:layout_height="@dimen/suggestion_card_icon_size"
+            android:tint="?android:attr/colorAccent"/>
+
+        <LinearLayout
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:paddingStart="@dimen/homepage_condition_full_card_padding_start"
+            android:paddingEnd="@dimen/homepage_condition_full_card_padding_end"
+            android:orientation="vertical">
+
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+                style="@style/TextAppearance.ConditionCardTitle"/>
+
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="@style/TextAppearance.ConditionCardSummary"/>
+
+        </LinearLayout>
+
+        <View
+            android:id="@+id/divider"
+            android:layout_width="@dimen/homepage_condition_full_card_divider_width"
+            android:layout_height="match_parent"
+            android:layout_marginTop="@dimen/homepage_condition_full_card_divider_padding_top"
+            android:layout_marginBottom="@dimen/homepage_condition_full_card_divider_padding_bottom"
+            android:background="?android:attr/dividerVertical" />
+
+        <Button
+            android:id="@+id/first_action"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/ConditionFullCardBorderlessButton"/>
+
+    </LinearLayout>
+
+</androidx.cardview.widget.CardView>
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
new file mode 100644
index 0000000..9cde951
--- /dev/null
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -0,0 +1,63 @@
+<?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.cardview.widget.CardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/homepage_condition_half_card_height"
+    style="@style/ContextualCardStyle">
+
+    <LinearLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/homepage_card_padding_start"
+        android:paddingEnd="@dimen/homepage_card_padding_end"
+        android:paddingTop="@dimen/homepage_condition_half_card_padding_top"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/suggestion_card_icon_size"
+            android:layout_height="@dimen/suggestion_card_icon_size"
+            android:tint="?android:attr/colorAccent"/>
+
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
+            android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+            style="@style/TextAppearance.ConditionCardTitle"/>
+
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            style="@style/TextAppearance.ConditionCardSummary"/>
+
+        <include layout="@layout/horizontal_divider"/>
+
+        <Button
+            android:id="@+id/first_action"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            style="@style/ConditionHalfCardBorderlessButton"/>
+
+    </LinearLayout>
+
+</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/res/layout/homepage_condition_tile.xml b/res/layout/homepage_condition_tile.xml
deleted file mode 100644
index ed76094..0000000
--- a/res/layout/homepage_condition_tile.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<!--
-     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.cardview.widget.CardView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    style="@style/ContextualCardStyle">
-
-    <LinearLayout
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:minHeight="@dimen/condition_header_height"
-            android:background="?android:attr/selectableItemBackground"
-            android:orientation="horizontal">
-
-            <ImageView
-                android:id="@android:id/icon"
-                android:layout_width="@dimen/suggestion_card_icon_size"
-                android:layout_height="@dimen/suggestion_card_icon_size"
-                android:layout_marginTop="12dp"
-                android:layout_marginStart="14dp"
-                android:layout_marginEnd="24dp"
-                android:tint="?android:attr/colorAccent"/>
-
-            <TextView
-                android:id="@android:id/title"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="14dp"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-        </LinearLayout>
-
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="62dp"
-            android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-            android:paddingBottom="8dp"
-            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
-            android:alpha=".7"
-            android:textColor="?android:attr/textColorPrimary"/>
-
-        <androidx.appcompat.widget.ButtonBarLayout
-            android:id="@+id/buttonBar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="62dp"
-            android:paddingBottom="1dp"
-            style="?android:attr/buttonBarStyle"
-            android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
-
-            <Button
-                android:id="@+id/first_action"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:paddingStart="0dp"
-                android:alpha=".8"
-                android:textAlignment="viewStart"
-                android:textColor="?android:attr/textColorPrimary"
-                style="?android:attr/buttonBarButtonStyle"/>
-
-            <Space
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"/>
-
-        </androidx.appcompat.widget.ButtonBarLayout>
-
-        <include layout="@layout/horizontal_divider"/>
-
-    </LinearLayout>
-
-</androidx.cardview.widget.CardView>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 18bcc38..c91ffb5 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -346,6 +346,16 @@
     <!-- Signal icon in NetworkSelectSetting -->
     <dimen name="signal_strength_icon_size">24dp</dimen>
 
-
+    <!-- Condition cards size and padding -->
+    <dimen name="homepage_condition_card_title_margin_bottom">2dp</dimen>
+    <dimen name="homepage_condition_half_card_height">150dp</dimen>
+    <dimen name="homepage_condition_half_card_padding_top">12dp</dimen>
+    <dimen name="homepage_condition_half_card_title_margin_top">12dp</dimen>
+    <dimen name="homepage_condition_full_card_height">72dp</dimen>
+    <dimen name="homepage_condition_full_card_padding_start">24dp</dimen>
+    <dimen name="homepage_condition_full_card_padding_end">24dp</dimen>
+    <dimen name="homepage_condition_full_card_divider_width">.75dp</dimen>
+    <dimen name="homepage_condition_full_card_divider_padding_top">12dp</dimen>
+    <dimen name="homepage_condition_full_card_divider_padding_bottom">12dp</dimen>
 
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e828ac2..4e07bad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9964,15 +9964,6 @@
     <!-- UI debug setting: ANGLE enabled app has been set [CHAR LIMIT=NONE] -->
     <string name="angle_enabled_app_set">ANGLE enabled application: <xliff:g id="app_name" example="com.company.app">%1$s</xliff:g></string>
 
-    <!-- Title for Directory Access settings -->
-    <string name="directory_access">Directory access</string>
-    <!-- Keywords for Directory Access settings -->
-    <string name="keywords_directory_access">directory access</string>
-
-    <!-- String used to describe the name of a directory in a volume; it must
-         show both names, with the directory name wrapped in parenthesis -->
-    <string name="directory_on_volume"><xliff:g id="volume" example="SD Card">%1$s</xliff:g> (<xliff:g id="directory" example="Movies">%2$s</xliff:g>)</string>
-
     <!-- Slices Strings -->
 
     <!-- Summary text on a card explaining that a setting does not exist / is not supported on the device [CHAR_LIMIT=NONE]-->
@@ -10060,7 +10051,7 @@
     <!-- Title for prevent ringing gesture screen -->
     <string name="gesture_prevent_ringing_screen_title">Prevent ringing</string>
     <!-- Title for prevent ringing setting -->
-    <string name="gesture_prevent_ringing_title">Press Power &amp; Volume Up together</string>
+    <string name="gesture_prevent_ringing_title">Press Power &amp; Volume Up together to</string>
     <!-- Title for prevent ringing setting -->
     <string name="gesture_prevent_ringing_sound_title">Shortcut to prevent ringing</string>
     <!-- Option for prevent ringing setting -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 83971b6..70d8a93 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -308,6 +308,16 @@
         <item name="android:textColor">?android:attr/colorAccent</item>
     </style>
 
+    <style name="TextAppearance.ConditionCardTitle"
+           parent="@android:style/TextAppearance.Material.Body2">
+        <item name="android:textSize">16sp</item>
+    </style>
+
+    <style name="TextAppearance.ConditionCardSummary"
+           parent="@android:style/TextAppearance.Material.Body1">
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
+    </style>
+
     <style name="TextAppearance.EntityHeaderTitle"
            parent="@android:style/TextAppearance.Material.Subhead">
         <item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -463,4 +473,24 @@
         <item name="cardElevation">@dimen/homepage_card_elevation</item>
     </style>
 
+    <style name="ConditionCardBorderlessButton"
+           parent="android:Widget.DeviceDefault.Button.Borderless">
+        <item name="android:textColor">?android:attr/colorAccent</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:textAllCaps">false</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
+    </style>
+
+    <style name="ConditionHalfCardBorderlessButton"
+           parent="@style/ConditionCardBorderlessButton">
+        <item name="android:textAlignment">viewStart</item>
+        <item name="android:paddingStart">0dp</item>
+    </style>
+
+    <style name="ConditionFullCardBorderlessButton"
+           parent="@style/ConditionCardBorderlessButton">
+        <item name="android:textAlignment">viewEnd</item>
+        <item name="android:paddingEnd">0dp</item>
+    </style>
+
 </resources>
diff --git a/res/xml/directory_access_details.xml b/res/xml/directory_access_details.xml
deleted file mode 100644
index 4448ba6..0000000
--- a/res/xml/directory_access_details.xml
+++ /dev/null
@@ -1,20 +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.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:settings="http://schemas.android.com/apk/res-auto"
-        android:key="directory_access_details"
-        android:title="@string/directory_access"/>
diff --git a/res/xml/prevent_ringing_gesture_settings.xml b/res/xml/prevent_ringing_gesture_settings.xml
index 5135664..62f0223 100644
--- a/res/xml/prevent_ringing_gesture_settings.xml
+++ b/res/xml/prevent_ringing_gesture_settings.xml
@@ -26,13 +26,8 @@
         app:animation="@raw/gesture_prevent_ringing"
         app:preview="@drawable/gesture_prevent_ringing" />
 
-    <ListPreference
-        android:key="gesture_prevent_ringing"
-        android:title="@string/gesture_prevent_ringing_title"
-        android:entries="@array/gesture_prevent_ringing_entries"
-        android:entryValues="@array/gesture_prevent_ringing_values"
-        app:controller="com.android.settings.gestures.PreventRingingPreferenceController"
-        app:keywords="@string/keywords_gesture"
-        app:allowDividerAbove="true" />
-
+    <PreferenceCategory
+        android:key="gesture_prevent_ringing_category"
+        android:title="@string/gesture_prevent_ringing_title">
+    </PreferenceCategory>
 </PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index a6c2159..57e673f 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -121,16 +121,6 @@
     </Preference>
 
     <Preference
-        android:key="special_app_directory_access"
-        android:title="@string/directory_access"
-        android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
-        settings:keywords="@string/keywords_directory_access">
-        <extra
-            android:name="classname"
-            android:value="com.android.settings.Settings$DirectoryAccessSettingsActivity" />
-    </Preference>
-
-    <Preference
         android:key="change_wifi_state"
         android:title="@string/change_wifi_state_title"
         android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 952c519..8cff5f1 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -120,7 +120,6 @@
     public static class PhotosStorageActivity extends SettingsActivity {
         /* empty */
     }
-    public static class DirectoryAccessSettingsActivity extends SettingsActivity { /* empty */ }
 
     public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
     public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 14a9e83..79caefe 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -979,4 +979,14 @@
             return packageManager.getDefaultActivityIcon();
         }
     }
+
+    /** Returns true if the current package is installed & enabled. */
+    public static boolean isPackageEnabled(Context context, String packageName) {
+        try {
+            return context.getPackageManager().getApplicationInfo(packageName, 0).enabled;
+        } catch (Exception e) {
+            Log.e(TAG, "Error while retrieving application info for package " + packageName, e);
+        }
+        return false;
+    }
 }
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 18e9906..78a8614 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -92,18 +92,18 @@
 
     @VisibleForTesting
     void finishIfAccountMissing() {
-        AccountManager accountManager = (AccountManager) getContext().getSystemService(
-                Context.ACCOUNT_SERVICE);
-        boolean accountExists = false;
-        for (Account account : accountManager.getAccountsByType(mAccount.type)) {
-            if (account.equals(mAccount)) {
-                accountExists = true;
-                break;
+        final Context context = getContext();
+        final UserManager um = context.getSystemService(UserManager.class);
+        final AccountManager accountManager = (AccountManager) context.getSystemService(
+                AccountManager.class);
+        for (UserHandle userHandle : um.getUserProfiles()) {
+            for (Account account : accountManager.getAccountsAsUser(userHandle.getIdentifier())) {
+                if (account.equals(mAccount)) {
+                    return;
+                }
             }
         }
-        if (!accountExists) {
-            finish();
-        }
+        finish();
     }
 
     @Override
@@ -177,4 +177,4 @@
             accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/applications/AppStateDirectoryAccessBridge.java b/src/com/android/settings/applications/AppStateDirectoryAccessBridge.java
deleted file mode 100644
index 1c2a0af..0000000
--- a/src/com/android/settings/applications/AppStateDirectoryAccessBridge.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-package com.android.settings.applications;
-
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES_COLUMNS;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES_COL_PACKAGE;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.settingslib.applications.ApplicationsState;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
-import com.android.settingslib.applications.ApplicationsState.AppFilter;
-
-import java.util.Set;
-
-// TODO(b/72055774): add unit tests
-public class AppStateDirectoryAccessBridge extends AppStateBaseBridge {
-
-    private static final String TAG = "DirectoryAccessBridge";
-
-    // TODO(b/72055774): set to false once feature is ready (or use Log.isLoggable)
-    static final boolean DEBUG = true;
-    static final boolean VERBOSE = true;
-
-    public AppStateDirectoryAccessBridge(ApplicationsState appState, Callback callback) {
-        super(appState, callback);
-    }
-
-    @Override
-    protected void loadAllExtraInfo() { }
-
-    @Override
-    protected void updateExtraInfo(AppEntry app, String pkg, int uid) { }
-
-    public static final AppFilter FILTER_APP_HAS_DIRECTORY_ACCESS = new AppFilter() {
-
-        private Set<String> mPackages;
-
-        @Override
-        public void init() {
-            throw new UnsupportedOperationException("Need to call constructor that takes context");
-        }
-
-        @Override
-        public void init(Context context) {
-            mPackages = null;
-            final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
-                    .authority(AUTHORITY).appendPath(TABLE_PACKAGES).appendPath("*")
-                    .build();
-            try (Cursor cursor = context.getContentResolver().query(providerUri,
-                    TABLE_PACKAGES_COLUMNS, null, null)) {
-                if (cursor == null) {
-                    Log.w(TAG, "Didn't get cursor for " + providerUri);
-                    return;
-                }
-                final int count = cursor.getCount();
-                if (count == 0) {
-                    if (DEBUG) {
-                        Log.d(TAG, "No packages anymore (was " + mPackages + ")");
-                    }
-                    return;
-                }
-                mPackages = new ArraySet<>(count);
-                while (cursor.moveToNext()) {
-                    mPackages.add(cursor.getString(TABLE_PACKAGES_COL_PACKAGE));
-                }
-                if (DEBUG) {
-                    Log.d(TAG, "init(): " + mPackages);
-                }
-            }
-        }
-
-
-        @Override
-        public boolean filterApp(AppEntry info) {
-            return mPackages != null && mPackages.contains(info.info.packageName);
-        }
-    };
-}
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index e24a210..c926da3 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -18,13 +18,10 @@
 
 import static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS;
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.GrantedUriPermission;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -32,7 +29,6 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -461,17 +457,6 @@
                 Context.ACTIVITY_SERVICE);
         am.clearGrantedUriPermissions(packageName);
 
-
-        // Also update the Scoped Directory Access UI permissions
-        final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
-                .build();
-        Log.v(TAG, "Asking " + providerUri + " to delete permissions for " + packageName);
-        final int deleted = context.getContentResolver().delete(providerUri, null, new String[] {
-                packageName
-        });
-        Log.d(TAG, "Deleted " + deleted + " entries for package " + packageName);
-
         // Update UI
         refreshGrantedUriPermissions();
     }
diff --git a/src/com/android/settings/applications/DirectoryAccessDetails.java b/src/com/android/settings/applications/DirectoryAccessDetails.java
deleted file mode 100644
index f158d81..0000000
--- a/src/com/android/settings/applications/DirectoryAccessDetails.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.settings.applications;
-
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_GRANTED;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract
-        .TABLE_PERMISSIONS_COLUMNS;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract
-        .TABLE_PERMISSIONS_COL_DIRECTORY;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract
-        .TABLE_PERMISSIONS_COL_GRANTED;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract
-        .TABLE_PERMISSIONS_COL_PACKAGE;
-import static android.os.storage.StorageVolume.ScopedAccessProviderContract
-        .TABLE_PERMISSIONS_COL_VOLUME_UUID;
-
-import static com.android.settings.applications.AppStateDirectoryAccessBridge.DEBUG;
-import static com.android.settings.applications.AppStateDirectoryAccessBridge.VERBOSE;
-
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.util.IconDrawableFactory;
-import android.util.Log;
-import android.util.Pair;
-
-import androidx.appcompat.app.AlertDialog;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.widget.EntityHeaderController;
-import com.android.settings.widget.EntityHeaderController.ActionType;
-import com.android.settingslib.applications.AppUtils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Detailed settings for an app's directory access permissions (A.K.A Scoped Directory Access).
- *
- * <p>Currently, it shows the entry for which the user denied access with the "Do not ask again"
- * flag checked on: the user than can use the settings toggle to reset that deniel.
- *
- * <p>This fragments dynamically lists all such permissions, starting with one preference per
- * directory in the primary storage, then adding additional entries for the external volumes (one
- * entry for the whole volume).
- */
-// TODO(b/72055774): add unit tests
-public class DirectoryAccessDetails extends AppInfoBase {
-
-    @SuppressWarnings("hiding")
-    private static final String TAG = "DirectoryAccessDetails";
-
-    private boolean mCreated;
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-
-        if (mCreated) {
-            Log.w(TAG, "onActivityCreated(): ignoring duplicate call");
-            return;
-        }
-        mCreated = true;
-        if (mPackageInfo == null) {
-            Log.w(TAG, "onActivityCreated(): no package info");
-            return;
-        }
-        final Activity activity = getActivity();
-        final Preference pref = EntityHeaderController
-                .newInstance(activity, this, /* header= */ null )
-                .setRecyclerView(getListView(), getSettingsLifecycle())
-                .setIcon(IconDrawableFactory.newInstance(getPrefContext())
-                        .getBadgedIcon(mPackageInfo.applicationInfo))
-                .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
-                .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
-                .setPackageName(mPackageName)
-                .setUid(mPackageInfo.applicationInfo.uid)
-                .setHasAppInfoLink(false)
-                .setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
-                .done(activity, getPrefContext());
-        getPreferenceScreen().addPreference(pref);
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        addPreferencesFromResource(R.xml.directory_access_details);
-
-    }
-
-    @Override
-    protected boolean refreshUi() {
-        final Context context = getPrefContext();
-        final PreferenceScreen prefsGroup = getPreferenceScreen();
-        prefsGroup.removeAll();
-
-        final Map<String, ExternalVolume> externalVolumes = new HashMap<>();
-
-        final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
-                .build();
-        // Query provider for entries.
-        try (Cursor cursor = context.getContentResolver().query(providerUri,
-                TABLE_PERMISSIONS_COLUMNS, null, new String[] { mPackageName }, null)) {
-            if (cursor == null) {
-                Log.w(TAG, "Didn't get cursor for " + mPackageName);
-                return true;
-            }
-            final int count = cursor.getCount();
-            if (count == 0) {
-                // This setting screen should not be reached if there was no permission, so just
-                // ignore it
-                Log.w(TAG, "No permissions for " + mPackageName);
-                return true;
-            }
-
-            while (cursor.moveToNext()) {
-                final String pkg = cursor.getString(TABLE_PERMISSIONS_COL_PACKAGE);
-                final String uuid = cursor.getString(TABLE_PERMISSIONS_COL_VOLUME_UUID);
-                final String dir = cursor.getString(TABLE_PERMISSIONS_COL_DIRECTORY);
-                final boolean granted = cursor.getInt(TABLE_PERMISSIONS_COL_GRANTED) == 1;
-                if (VERBOSE) {
-                    Log.v(TAG, "Pkg:"  + pkg + " uuid: " + uuid + " dir: " + dir
-                            + " granted:" + granted);
-                }
-
-                if (!mPackageName.equals(pkg)) {
-                    // Sanity check, shouldn't happen
-                    Log.w(TAG, "Ignoring " + uuid + "/" + dir + " due to package mismatch: "
-                            + "expected " + mPackageName + ", got " + pkg);
-                    continue;
-                }
-
-                if (uuid == null) {
-                    if (dir == null) {
-                        // Sanity check, shouldn't happen
-                        Log.wtf(TAG, "Ignoring permission on primary storage root");
-                    } else {
-                        // Primary storage entry: add right away
-                        prefsGroup.addPreference(newPreference(context, dir, providerUri,
-                                /* uuid= */ null, dir, granted, /* children= */ null));
-                    }
-                } else {
-                    // External volume entry: save it for later.
-                    ExternalVolume externalVolume = externalVolumes.get(uuid);
-                    if (externalVolume == null) {
-                        externalVolume = new ExternalVolume(uuid);
-                        externalVolumes.put(uuid, externalVolume);
-                    }
-                    if (dir == null) {
-                        // Whole volume
-                        externalVolume.granted = granted;
-                    } else {
-                        // Directory only
-                        externalVolume.children.add(new Pair<>(dir, granted));
-                    }
-                }
-            }
-        }
-
-        if (VERBOSE) {
-            Log.v(TAG, "external volumes: " + externalVolumes);
-        }
-
-        if (externalVolumes.isEmpty()) {
-            // We're done!
-            return true;
-        }
-
-        // Add entries from external volumes
-
-        // Query StorageManager to get the user-friendly volume names.
-        final StorageManager sm = context.getSystemService(StorageManager.class);
-        final List<VolumeInfo> volumes = sm.getVolumes();
-        if (volumes.isEmpty()) {
-            Log.w(TAG, "StorageManager returned no secondary volumes");
-            return true;
-        }
-        final Map<String, String> volumeNames = new HashMap<>(volumes.size());
-        for (VolumeInfo volume : volumes) {
-            final String uuid = volume.getFsUuid();
-            if (uuid == null) continue; // Primary storage; not used.
-
-            String name = sm.getBestVolumeDescription(volume);
-            if (name == null) {
-                Log.w(TAG, "No description for " + volume + "; using uuid instead: " + uuid);
-                name = uuid;
-            }
-            volumeNames.put(uuid, name);
-        }
-        if (VERBOSE) {
-            Log.v(TAG, "UUID -> name mapping: " + volumeNames);
-        }
-
-        for (ExternalVolume volume : externalVolumes.values()) {
-            final String volumeName = volumeNames.get(volume.uuid);
-            if (volumeName == null) {
-                Log.w(TAG, "Ignoring entry for invalid UUID: " + volume.uuid);
-                continue;
-            }
-            // First add the pref for the whole volume...
-            final PreferenceCategory category = new PreferenceCategory(context);
-            prefsGroup.addPreference(category);
-            final Set<SwitchPreference> children = new HashSet<>(volume.children.size());
-            category.addPreference(newPreference(context, volumeName, providerUri, volume.uuid,
-                    /* dir= */ null, volume.granted, children));
-
-            // ... then the children prefs
-            volume.children.forEach((pair) -> {
-                final String dir = pair.first;
-                final String name = context.getResources()
-                        .getString(R.string.directory_on_volume, volumeName, dir);
-                final SwitchPreference childPref =
-                        newPreference(context, name, providerUri, volume.uuid, dir, pair.second,
-                                /* children= */ null);
-                category.addPreference(childPref);
-                children.add(childPref);
-            });
-        }
-        return true;
-    }
-
-    private SwitchPreference newPreference(Context context, String title, Uri providerUri,
-            String uuid, String dir, boolean granted, @Nullable Set<SwitchPreference> children) {
-        final SwitchPreference pref = new SwitchPreference(context);
-        pref.setKey(String.format("%s:%s", uuid, dir));
-        pref.setTitle(title);
-        pref.setChecked(granted);
-        pref.setOnPreferenceChangeListener((unused, value) -> {
-            if (!Boolean.class.isInstance(value)) {
-                // Sanity check
-                Log.wtf(TAG, "Invalid value from switch: " + value);
-                return true;
-            }
-            final boolean newValue = ((Boolean) value).booleanValue();
-
-            resetDoNotAskAgain(context, newValue, providerUri, uuid, dir);
-            if (children != null) {
-                // When parent is granted, children should be hidden; and vice versa
-                final boolean newChildValue = !newValue;
-                for (SwitchPreference child : children) {
-                    child.setVisible(newChildValue);
-                }
-            }
-            return true;
-        });
-        return pref;
-    }
-
-    private void resetDoNotAskAgain(Context context, boolean newValue, Uri providerUri,
-            @Nullable String uuid, @Nullable String directory) {
-        if (DEBUG) {
-            Log.d(TAG, "Asking " + providerUri  + " to update " + uuid + "/" + directory + " to "
-                    + newValue);
-        }
-        final ContentValues values = new ContentValues(1);
-        values.put(COL_GRANTED, newValue);
-        final int updated = context.getContentResolver().update(providerUri, values,
-                null, new String[] { mPackageName, uuid, directory });
-        if (DEBUG) {
-            Log.d(TAG, "Updated " + updated + " entries for " + uuid + "/" + directory);
-        }
-    }
-
-    @Override
-    protected AlertDialog createDialog(int id, int errorCode) {
-        return null;
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.APPLICATIONS_DIRECTORY_ACCESS_DETAIL;
-    }
-
-    private static class ExternalVolume {
-        final String uuid;
-        final List<Pair<String, Boolean>> children = new ArrayList<>();
-        boolean granted;
-
-        ExternalVolume(String uuid) {
-            this.uuid = uuid;
-        }
-
-        @Override
-        public String toString() {
-            return "ExternalVolume: [uuid=" + uuid + ", granted=" + granted +
-                    ", children=" + children + "]";
-        }
-    }
-}
diff --git a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
index 7d1e159..0d2bcab 100644
--- a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
+++ b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
@@ -19,7 +19,6 @@
 import androidx.annotation.IntDef;
 
 import com.android.settings.R;
-import com.android.settings.applications.AppStateDirectoryAccessBridge;
 import com.android.settings.applications.AppStateInstallAppsBridge;
 import com.android.settings.applications.AppStateNotificationBridge;
 import com.android.settings.applications.AppStateOverlayBridge;
@@ -70,7 +69,6 @@
     public static final int FILTER_APPS_WITH_OVERLAY = 11;
     public static final int FILTER_APPS_WRITE_SETTINGS = 12;
     public static final int FILTER_APPS_INSTALL_SOURCES = 13;
-    public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 14;
     public static final int FILTER_APP_CAN_CHANGE_WIFI_STATE = 15;
     public static final int FILTER_APPS_BLOCKED = 16;
     // Next id: 17
@@ -170,12 +168,6 @@
                 FILTER_APPS_INSTALL_SOURCES,
                 R.string.filter_install_sources_apps);
 
-        // Apps that interacted with directory access permissions (A.K.A. Scoped Directory Access)
-        mFilters[FILTER_APP_HAS_DIRECTORY_ACCESS] = new AppFilterItem(
-                AppStateDirectoryAccessBridge.FILTER_APP_HAS_DIRECTORY_ACCESS,
-                FILTER_APP_HAS_DIRECTORY_ACCESS,
-                R.string.filter_install_sources_apps);
-
         mFilters[FILTER_APP_CAN_CHANGE_WIFI_STATE] = new AppFilterItem(
                 AppStateChangeWifiStateBridge.FILTER_CHANGE_WIFI_STATE,
                 FILTER_APP_CAN_CHANGE_WIFI_STATE,
@@ -208,8 +200,6 @@
                 return FILTER_APPS_WRITE_SETTINGS;
             case ManageApplications.LIST_TYPE_MANAGE_SOURCES:
                 return FILTER_APPS_INSTALL_SOURCES;
-            case ManageApplications.LIST_TYPE_DIRECTORY_ACCESS:
-                return FILTER_APP_HAS_DIRECTORY_ACCESS;
             case ManageApplications.LIST_TYPE_WIFI_ACCESS:
                 return FILTER_APP_CAN_CHANGE_WIFI_STATE;
             case ManageApplications.LIST_TYPE_NOTIFICATION:
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 44ea575..6b2fb91 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -90,7 +90,6 @@
 import com.android.settings.applications.AppInfoBase;
 import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
 import com.android.settings.applications.AppStateBaseBridge;
-import com.android.settings.applications.AppStateDirectoryAccessBridge;
 import com.android.settings.applications.AppStateInstallAppsBridge;
 import com.android.settings.applications.AppStateNotificationBridge;
 import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
@@ -101,7 +100,6 @@
 import com.android.settings.applications.AppStateWriteSettingsBridge;
 import com.android.settings.applications.AppStorageSettings;
 import com.android.settings.applications.DefaultAppSettings;
-import com.android.settings.applications.DirectoryAccessDetails;
 import com.android.settings.applications.InstalledAppCounter;
 import com.android.settings.applications.UsageAccessDetails;
 import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
@@ -218,7 +216,6 @@
     public static final int LIST_TYPE_GAMES = 9;
     public static final int LIST_TYPE_MOVIES = 10;
     public static final int LIST_TYPE_PHOTOGRAPHY = 11;
-    public static final int LIST_TYPE_DIRECTORY_ACCESS = 12;
     public static final int LIST_TYPE_WIFI_ACCESS = 13;
 
     // List types that should show instant apps.
@@ -293,9 +290,6 @@
             mListType = LIST_TYPE_PHOTOGRAPHY;
             mSortOrder = R.id.sort_order_size;
             mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
-        } else if (className.equals(Settings.DirectoryAccessSettingsActivity.class.getName())) {
-            mListType = LIST_TYPE_DIRECTORY_ACCESS;
-            screenTitle = R.string.directory_access;
         } else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
             mListType = LIST_TYPE_WIFI_ACCESS;
             screenTitle = R.string.change_wifi_state_title;
@@ -479,8 +473,6 @@
                 return MetricsEvent.SYSTEM_ALERT_WINDOW_APPS;
             case LIST_TYPE_MANAGE_SOURCES:
                 return MetricsEvent.MANAGE_EXTERNAL_SOURCES;
-            case LIST_TYPE_DIRECTORY_ACCESS:
-                return MetricsEvent.DIRECTORY_ACCESS;
             case LIST_TYPE_WIFI_ACCESS:
                 return MetricsEvent.CONFIGURE_WIFI;
             default:
@@ -578,9 +570,6 @@
             case LIST_TYPE_PHOTOGRAPHY:
                 startAppInfoFragment(AppStorageSettings.class, R.string.storage_photos_videos);
                 break;
-            case LIST_TYPE_DIRECTORY_ACCESS:
-                startAppInfoFragment(DirectoryAccessDetails.class, R.string.directory_access);
-                break;
             case LIST_TYPE_WIFI_ACCESS:
                 startAppInfoFragment(ChangeWifiStateDetails.class,
                         R.string.change_wifi_state_title);
@@ -916,8 +905,6 @@
                 mExtraInfoBridge = new AppStateWriteSettingsBridge(mContext, mState, this);
             } else if (mManageApplications.mListType == LIST_TYPE_MANAGE_SOURCES) {
                 mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this);
-            } else if (mManageApplications.mListType == LIST_TYPE_DIRECTORY_ACCESS) {
-                mExtraInfoBridge = new AppStateDirectoryAccessBridge(mState, this);
             } else if (mManageApplications.mListType == LIST_TYPE_WIFI_ACCESS) {
                 mExtraInfoBridge = new AppStateChangeWifiStateBridge(mContext, mState, this);
             } else {
@@ -1360,9 +1347,6 @@
                 case LIST_TYPE_MANAGE_SOURCES:
                     holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry));
                     break;
-                case LIST_TYPE_DIRECTORY_ACCESS:
-                    holder.setSummary(null);
-                    break;
                 case LIST_TYPE_WIFI_ACCESS:
                     holder.setSummary(ChangeWifiStateDetails.getSummary(mContext, entry));
                     break;
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 4346973..f61cb0c 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -34,7 +34,6 @@
 import com.android.settings.accounts.ManagedProfileSettings;
 import com.android.settings.applications.AppAndNotificationDashboardFragment;
 import com.android.settings.applications.DefaultAppSettings;
-import com.android.settings.applications.DirectoryAccessDetails;
 import com.android.settings.applications.ProcessStatsSummary;
 import com.android.settings.applications.ProcessStatsUi;
 import com.android.settings.applications.UsageAccessDetails;
@@ -258,7 +257,6 @@
             LockscreenDashboardFragment.class.getName(),
             BluetoothDeviceDetailsFragment.class.getName(),
             DataUsageList.class.getName(),
-            DirectoryAccessDetails.class.getName(),
             ToggleBackupSettingFragment.class.getName(),
             PreviouslyConnectedDeviceDashboardFragment.class.getName(),
     };
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 2d95c31..65181c4 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -63,7 +63,7 @@
         implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy {
     @VisibleForTesting
     static final boolean USE_FAKE_DATA = false;
-    private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
+    private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20;
     private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
     private static final int STATS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
 
diff --git a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
index 069085b..2e9b5a5 100644
--- a/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
+++ b/src/com/android/settings/gestures/GesturesSettingPreferenceController.java
@@ -20,8 +20,6 @@
 import android.content.Context;
 import android.provider.Settings;
 
-import androidx.annotation.NonNull;
-
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
@@ -31,6 +29,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import androidx.annotation.NonNull;
+
 public class GesturesSettingPreferenceController extends BasePreferenceController {
     private final AssistGestureFeatureProvider mFeatureProvider;
     private List<AbstractPreferenceController> mGestureControllers;
@@ -76,7 +76,7 @@
                 .setConfig(ambientDisplayConfiguration));
         controllers.add(new DoubleTapScreenPreferenceController(context, FAKE_PREF_KEY)
                 .setConfig(ambientDisplayConfiguration));
-        controllers.add(new PreventRingingPreferenceController(context, FAKE_PREF_KEY));
+        controllers.add(new PreventRingingParentPreferenceController(context, FAKE_PREF_KEY));
         return controllers;
     }
 
diff --git a/src/com/android/settings/gestures/PreventRingingGesturePreferenceController.java b/src/com/android/settings/gestures/PreventRingingGesturePreferenceController.java
new file mode 100644
index 0000000..cb9bf4f
--- /dev/null
+++ b/src/com/android/settings/gestures/PreventRingingGesturePreferenceController.java
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.gestures;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.Settings;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.widget.RadioButtonPreference;
+import com.android.settings.widget.VideoPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreate;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+public class PreventRingingGesturePreferenceController extends AbstractPreferenceController
+        implements RadioButtonPreference.OnClickListener, LifecycleObserver, OnSaveInstanceState,
+        OnResume, OnPause, OnCreate, PreferenceControllerMixin {
+
+    @VisibleForTesting static final String KEY_VIBRATE = "prevent_ringing_option_vibrate";
+    @VisibleForTesting static final String KEY_NONE = "prevent_ringing_option_none";
+    @VisibleForTesting static final String KEY_MUTE = "prevent_ringing_option_mute";
+
+    private final String KEY_VIDEO_PAUSED = "key_video_paused";
+    private final String PREF_KEY_VIDEO = "gesture_prevent_ringing_video";
+    private final String KEY = "gesture_prevent_ringing_category";
+    private final Context mContext;
+
+    private VideoPreference mVideoPreference;
+    private boolean mVideoPaused;
+
+    private PreferenceCategory mPreferenceCategory;
+    @VisibleForTesting RadioButtonPreference mVibratePref;
+    @VisibleForTesting RadioButtonPreference mNonePref;
+    @VisibleForTesting RadioButtonPreference mMutePref;
+
+    private SettingObserver mSettingObserver;
+
+    public PreventRingingGesturePreferenceController(Context context, Lifecycle lifecycle) {
+        super(context);
+        mContext = context;
+
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+        }
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            mPreferenceCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
+            mVibratePref = makeRadioPreference(KEY_VIBRATE, R.string.prevent_ringing_option_vibrate);
+            mMutePref = makeRadioPreference(KEY_MUTE, R.string.prevent_ringing_option_mute);
+            mNonePref = makeRadioPreference(KEY_NONE, R.string.prevent_ringing_option_none);
+
+            if (mPreferenceCategory != null) {
+                mSettingObserver = new SettingObserver(mPreferenceCategory);
+            }
+
+            mVideoPreference = (VideoPreference) screen.findPreference(getVideoPrefKey());
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_volumeHushGestureEnabled);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY;
+    }
+
+    public String getVideoPrefKey() {
+        return PREF_KEY_VIDEO;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(KEY_VIDEO_PAUSED, mVideoPaused);
+    }
+
+    @Override
+    public void onRadioButtonClicked(RadioButtonPreference preference) {
+        int preventRingingSetting = keyToSetting(preference.getKey());
+        if (preventRingingSetting != Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE)) {
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.VOLUME_HUSH_GESTURE, preventRingingSetting);
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        int preventRingingSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE);
+
+        final boolean isVibrate = preventRingingSetting == Settings.Secure.VOLUME_HUSH_VIBRATE;
+        final boolean isMute = preventRingingSetting == Settings.Secure.VOLUME_HUSH_MUTE;
+        final boolean isOff = preventRingingSetting == Settings.Secure.VOLUME_HUSH_OFF
+                || (!isVibrate && !isMute);
+        if (mVibratePref != null && mVibratePref.isChecked() != isVibrate) {
+            mVibratePref.setChecked(isVibrate);
+        }
+        if (mMutePref != null && mMutePref.isChecked() != isMute) {
+            mMutePref.setChecked(isMute);
+        }
+        if (mNonePref != null && mNonePref.isChecked() != isOff) {
+            mNonePref.setChecked(isOff);
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        if (savedInstanceState != null) {
+            mVideoPaused = savedInstanceState.getBoolean(KEY_VIDEO_PAUSED, false);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(mContext.getContentResolver());
+            mSettingObserver.onChange(false, null);
+        }
+
+        if (mVideoPreference != null) {
+            mVideoPreference.onViewVisible(mVideoPaused);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mSettingObserver != null) {
+            mSettingObserver.unregister(mContext.getContentResolver());
+        }
+
+        if (mVideoPreference != null) {
+            mVideoPaused = mVideoPreference.isVideoPaused();
+            mVideoPreference.onViewInvisible();
+        }
+    }
+
+    private int keyToSetting(String key) {
+        switch (key) {
+            case KEY_NONE:
+                return Settings.Secure.VOLUME_HUSH_OFF;
+            case KEY_MUTE:
+                return Settings.Secure.VOLUME_HUSH_MUTE;
+            case KEY_VIBRATE:
+            default:
+                return Settings.Secure.VOLUME_HUSH_VIBRATE;
+        }
+    }
+
+    private RadioButtonPreference makeRadioPreference(String key, int titleId) {
+        RadioButtonPreference pref = new RadioButtonPreference(mPreferenceCategory.getContext());
+        pref.setKey(key);
+        pref.setTitle(titleId);
+        pref.setOnClickListener(this);
+        mPreferenceCategory.addPreference(pref);
+        return pref;
+    }
+
+    private class SettingObserver extends ContentObserver {
+        private final Uri VOLUME_HUSH_GESTURE = Settings.Secure.getUriFor(
+                Settings.Secure.VOLUME_HUSH_GESTURE);
+
+        private final Preference mPreference;
+
+        public SettingObserver(Preference preference) {
+            super(new Handler());
+            mPreference = preference;
+        }
+
+        public void register(ContentResolver cr) {
+            cr.registerContentObserver(VOLUME_HUSH_GESTURE, false, this);
+        }
+
+        public void unregister(ContentResolver cr) {
+            cr.unregisterContentObserver(this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            if (uri == null || VOLUME_HUSH_GESTURE.equals(uri)) {
+                updateState(mPreference);
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/gestures/PreventRingingGestureSettings.java b/src/com/android/settings/gestures/PreventRingingGestureSettings.java
index 84b4e16..3e8ae85 100644
--- a/src/com/android/settings/gestures/PreventRingingGestureSettings.java
+++ b/src/com/android/settings/gestures/PreventRingingGestureSettings.java
@@ -23,8 +23,11 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.search.SearchIndexable;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -40,6 +43,18 @@
     }
 
     @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context, getSettingsLifecycle());
+    }
+
+    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
+            Lifecycle lifecycle) {
+        List<AbstractPreferenceController> controllers = new ArrayList<>();
+        controllers.add(new PreventRingingGesturePreferenceController(context, lifecycle));
+        return controllers;
+    }
+
+    @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_PREVENT_RINGING;
     }
@@ -68,6 +83,12 @@
                     sir.xmlResId = R.xml.prevent_ringing_gesture_settings;
                     return Arrays.asList(sir);
                 }
+
+                @Override
+                public List<AbstractPreferenceController> createPreferenceControllers(
+                        Context context) {
+                    return buildPreferenceControllers(context, null);
+                }
             };
 
 }
diff --git a/src/com/android/settings/gestures/PreventRingingPreferenceController.java b/src/com/android/settings/gestures/PreventRingingPreferenceController.java
deleted file mode 100644
index 570c1c6..0000000
--- a/src/com/android/settings/gestures/PreventRingingPreferenceController.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.settings.gestures;
-
-import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
-import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
-import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.provider.Settings;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.widget.VideoPreference;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnCreate;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
-
-public class PreventRingingPreferenceController extends PreventRingingParentPreferenceController
-        implements Preference.OnPreferenceChangeListener,
-        LifecycleObserver, OnResume, OnPause, OnCreate, OnSaveInstanceState {
-
-    private static final String PREF_KEY_VIDEO = "gesture_prevent_ringing_video";
-    @VisibleForTesting
-    static final String KEY_VIDEO_PAUSED = "key_video_paused";
-
-    private VideoPreference mVideoPreference;
-    @VisibleForTesting
-    boolean mVideoPaused;
-
-    public PreventRingingPreferenceController(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        final int status = super.getAvailabilityStatus();
-        if (status == AVAILABLE_UNSEARCHABLE) {
-            return AVAILABLE;
-        }
-        return status;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        if (isAvailable()) {
-            mVideoPreference = (VideoPreference) screen.findPreference(getVideoPrefKey());
-        }
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        super.updateState(preference);
-        if (preference != null) {
-            if (preference instanceof ListPreference) {
-                ListPreference pref = (ListPreference) preference;
-                int value = Settings.Secure.getInt(
-                        mContext.getContentResolver(), SECURE_KEY, VOLUME_HUSH_VIBRATE);
-                switch (value) {
-                    case VOLUME_HUSH_VIBRATE:
-                        pref.setValue(String.valueOf(value));
-                        break;
-                    case VOLUME_HUSH_MUTE:
-                        pref.setValue(String.valueOf(value));
-                        break;
-                    default:
-                        pref.setValue(String.valueOf(VOLUME_HUSH_OFF));
-                }
-            }
-        }
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        if (savedInstanceState != null) {
-            mVideoPaused = savedInstanceState.getBoolean(KEY_VIDEO_PAUSED, false);
-        }
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        outState.putBoolean(KEY_VIDEO_PAUSED, mVideoPaused);
-    }
-
-    @Override
-    public void onPause() {
-        if (mVideoPreference != null) {
-            mVideoPaused = mVideoPreference.isVideoPaused();
-            mVideoPreference.onViewInvisible();
-        }
-    }
-
-    @Override
-    public void onResume() {
-        if (mVideoPreference != null) {
-            mVideoPreference.onViewVisible(mVideoPaused);
-        }
-    }
-
-    protected String getVideoPrefKey() {
-        return PREF_KEY_VIDEO;
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        int value = Integer.parseInt((String) newValue);
-        Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY, value);
-        preference.setSummary(getSummary());
-        return true;
-    }
-}
diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
index 647d718..0065f5c 100644
--- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.homepage.contextualcards;
 
+import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
@@ -30,7 +31,7 @@
 public class CardDatabaseHelper extends SQLiteOpenHelper {
     private static final String TAG = "CardDatabaseHelper";
     private static final String DATABASE_NAME = "homepage_cards.db";
-    private static final int DATABASE_VERSION = 4;
+    private static final int DATABASE_VERSION = 5;
 
     public static final String CARD_TABLE = "cards";
 
@@ -119,6 +120,11 @@
          * Decide the card display full-length width or half-width in screen.
          */
         String SUPPORT_HALF_WIDTH = "support_half_width";
+
+        /**
+         * Decide the card is dismissed or not.
+         */
+        String CARD_DISMISSED = "card_dismissed";
     }
 
     private static final String CREATE_CARD_TABLE =
@@ -157,6 +163,8 @@
                     CardColumns.EXPIRE_TIME_MS +
                     " INTEGER, " +
                     CardColumns.SUPPORT_HALF_WIDTH +
+                    " INTEGER DEFAULT 0, " +
+                    CardColumns.CARD_DISMISSED +
                     " INTEGER DEFAULT 0 " +
                     ");";
 
@@ -190,9 +198,27 @@
 
     Cursor getContextualCards() {
         final SQLiteDatabase db = this.getReadableDatabase();
-        Cursor cursor = db.query(CARD_TABLE, null /* columns */, null /* selection */,
+        final String selection = CardColumns.CARD_DISMISSED + "=0";
+        Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
                 null /* selectionArgs */, null /* groupBy */, null /* having */,
                 null /* orderBy */);
         return cursor;
     }
+
+    /**
+     * Mark a specific ContextualCard with dismissal flag in the database to indicate that the
+     * card has been dismissed.
+     *
+     * @param cardName the card name of the ContextualCard which is dismissed by user.
+     * @return updated row number
+     */
+    public int markContextualCardAsDismissed(String cardName) {
+        final SQLiteDatabase database = this.getWritableDatabase();
+        final ContentValues values = new ContentValues();
+        values.put(CardColumns.CARD_DISMISSED, 1);
+        final String selection = CardColumns.NAME + "=?";
+        final String[] selectionArgs = {cardName};
+        final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
+        return rowsUpdated;
+    }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCard.java b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
index 996c2dd..b0dfad8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCard.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
@@ -42,6 +42,7 @@
         int CONDITIONAL = 3;
     }
 
+    private final Builder mBuilder;
     private final String mName;
     @CardType
     private final int mCardType;
@@ -142,7 +143,12 @@
         return TextUtils.isEmpty(mSliceUri);
     }
 
+    public Builder mutate() {
+        return mBuilder;
+    }
+
     public ContextualCard(Builder builder) {
+        mBuilder = builder;
         mName = builder.mName;
         mCardType = builder.mCardType;
         mRankingScore = builder.mRankingScore;
@@ -164,28 +170,47 @@
     }
 
     ContextualCard(Cursor c) {
+        mBuilder = new Builder();
         mName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.NAME));
+        mBuilder.setName(mName);
         mCardType = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.TYPE));
+        mBuilder.setCardType(mCardType);
         mRankingScore = c.getDouble(c.getColumnIndex(CardDatabaseHelper.CardColumns.SCORE));
+        mBuilder.setRankingScore(mRankingScore);
         mSliceUri = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SLICE_URI));
+        mBuilder.setSliceUri(Uri.parse(mSliceUri));
         mCategory = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CATEGORY));
+        mBuilder.setCategory(mCategory);
         mLocalizedToLocale = c.getString(
                 c.getColumnIndex(CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE));
+        mBuilder.setLocalizedToLocale(mLocalizedToLocale);
         mPackageName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.PACKAGE_NAME));
+        mBuilder.setPackageName(mPackageName);
         mAppVersion = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.APP_VERSION));
+        mBuilder.setAppVersion(mAppVersion);
         mTitleResName = c.getString(
                 c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_RES_NAME));
+        mBuilder.setTitleResName(mTitleResName);
         mTitleText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.TITLE_TEXT));
+        mBuilder.setTitleText(mTitleText);
         mSummaryResName = c.getString(
                 c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME));
+        mBuilder.setSummaryResName(mSummaryResName);
         mSummaryText = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.SUMMARY_TEXT));
+        mBuilder.setSummaryText(mSummaryText);
         mIconResName = c.getString(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_NAME));
+        mBuilder.setIconResName(mIconResName);
         mIconResId = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.ICON_RES_ID));
+        mBuilder.setIconResId(mIconResId);
         mCardAction = c.getInt(c.getColumnIndex(CardDatabaseHelper.CardColumns.CARD_ACTION));
+        mBuilder.setCardAction(mCardAction);
         mExpireTimeMS = c.getLong(c.getColumnIndex(CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS));
+        mBuilder.setExpireTimeMS(mExpireTimeMS);
         mIsHalfWidth = (c.getInt(
                 c.getColumnIndex(CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH)) == 1);
+        mBuilder.setIsHalfWidth(mIsHalfWidth);
         mIconDrawable = null;
+        mBuilder.setIconDrawable(mIconDrawable);
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java
index 0268fb0..2253a2f 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTable.java
@@ -16,43 +16,61 @@
 
 package com.android.settings.homepage.contextualcards;
 
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settings.homepage.contextualcards.ContextualCard.CardType;
 import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardController;
 import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
 import com.android.settings.homepage.contextualcards.slices.SliceContextualCardController;
 import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;
 
+import java.util.Comparator;
+import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.stream.Collectors;
 
 public class ContextualCardLookupTable {
-
+    private static final String TAG = "ContextualCardLookup";
     static class ControllerRendererMapping implements Comparable<ControllerRendererMapping> {
         @CardType
-        private final int mCardType;
-        private final Class<? extends ContextualCardController> mControllerClass;
-        private final Class<? extends ContextualCardRenderer> mRendererClass;
+        final int mCardType;
+        final int mViewType;
+        final Class<? extends ContextualCardController> mControllerClass;
+        final Class<? extends ContextualCardRenderer> mRendererClass;
 
-        private ControllerRendererMapping(@CardType int cardType,
+        ControllerRendererMapping(@CardType int cardType, int viewType,
                 Class<? extends ContextualCardController> controllerClass,
                 Class<? extends ContextualCardRenderer> rendererClass) {
             mCardType = cardType;
+            mViewType = viewType;
             mControllerClass = controllerClass;
             mRendererClass = rendererClass;
         }
 
         @Override
         public int compareTo(ControllerRendererMapping other) {
-            return Integer.compare(this.mCardType, other.mCardType);
+            return Comparator.comparingInt((ControllerRendererMapping mapping) -> mapping.mCardType)
+                    .thenComparingInt(mapping -> mapping.mViewType)
+                    .compare(this, other);
         }
     }
 
-    private static final Set<ControllerRendererMapping> LOOKUP_TABLE =
+    @VisibleForTesting
+    static final Set<ControllerRendererMapping> LOOKUP_TABLE =
             new TreeSet<ControllerRendererMapping>() {{
                 add(new ControllerRendererMapping(CardType.CONDITIONAL,
+                        ConditionContextualCardRenderer.HALF_WIDTH_VIEW_TYPE,
+                        ConditionContextualCardController.class,
+                        ConditionContextualCardRenderer.class));
+                add(new ControllerRendererMapping(CardType.CONDITIONAL,
+                        ConditionContextualCardRenderer.FULL_WIDTH_VIEW_TYPE,
                         ConditionContextualCardController.class,
                         ConditionContextualCardRenderer.class));
                 add(new ControllerRendererMapping(CardType.SLICE,
+                        SliceContextualCardRenderer.VIEW_TYPE,
                         SliceContextualCardController.class,
                         SliceContextualCardRenderer.class));
             }};
@@ -67,14 +85,27 @@
         return null;
     }
 
-    //TODO(b/112578070): Implement multi renderer cases.
-    public static Class<? extends ContextualCardRenderer> getCardRendererClasses(
+    public static Class<? extends ContextualCardRenderer> getCardRendererClassByCardType(
             @CardType int cardType) {
-        for (ControllerRendererMapping mapping : LOOKUP_TABLE) {
-            if (mapping.mCardType == cardType) {
-                return mapping.mRendererClass;
-            }
+        return LOOKUP_TABLE.stream()
+                .filter(m -> m.mCardType == cardType)
+                .findFirst()
+                .map(mapping -> mapping.mRendererClass)
+                .orElse(null);
+    }
+
+    public static Class<? extends ContextualCardRenderer> getCardRendererClassByViewType(
+            int viewType) throws IllegalStateException {
+        List<ControllerRendererMapping> validMappings = LOOKUP_TABLE.stream()
+                .filter(m -> m.mViewType == viewType).collect(Collectors.toList());
+        if (validMappings == null || validMappings.isEmpty()) {
+            Log.w(TAG, "No matching mapping");
+            return null;
         }
-        return null;
+        if (validMappings.size() != 1) {
+            throw new IllegalStateException("Have duplicate VIEW_TYPE in lookup table.");
+        }
+
+        return validMappings.get(0).mRendererClass;
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 51bef87..9bd08c8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -84,7 +84,7 @@
         final CardContentLoaderCallbacks cardContentLoaderCallbacks =
                 new CardContentLoaderCallbacks(mContext);
         cardContentLoaderCallbacks.setListener(this);
-        LoaderManager.getInstance(fragment).initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
+        LoaderManager.getInstance(fragment).restartLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
                 cardContentLoaderCallbacks);
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java
index 689b572..bb85bd2 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardRenderer.java
@@ -26,9 +26,9 @@
 public interface ContextualCardRenderer {
 
     /**
-     * The layout type of the controller.
+     * The layout type of the renderer.
      */
-    int getViewType();
+    int getViewType(boolean isHalfWidth);
 
     /**
      * When {@link ContextualCardsAdapter} calls {@link ContextualCardsAdapter#onCreateViewHolder},
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
index 865d242..0a8749d 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
@@ -61,26 +61,26 @@
 
     @Override
     public int getItemViewType(int position) {
-        return mContextualCards.get(position).getCardType();
+        final ContextualCard card = mContextualCards.get(position);
+        final ContextualCardRenderer renderer = mControllerRendererPool.getRendererByCardType(
+                mContext, mLifecycleOwner, card.getCardType());
+        return renderer.getViewType(card.isHalfWidth());
     }
 
     @Override
-    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int cardType) {
-        final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
-                mLifecycleOwner, cardType);
-        final int viewType = renderer.getViewType();
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        final ContextualCardRenderer renderer = mControllerRendererPool.getRendererByViewType(
+                mContext, mLifecycleOwner, viewType);
         final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
-
         return renderer.createViewHolder(view);
     }
 
     @Override
     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
-        final int cardType = mContextualCards.get(position).getCardType();
-        final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
-                mLifecycleOwner, cardType);
-
-        renderer.bindView(holder, mContextualCards.get(position));
+        final ContextualCard card = mContextualCards.get(position);
+        final ContextualCardRenderer renderer = mControllerRendererPool.getRendererByCardType(
+                mContext, mLifecycleOwner, card.getCardType());
+        renderer.bindView(holder, card);
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index d82fdfe..29eea4b 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -43,6 +43,11 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle());
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
         mContextualCardManager.loadContextualCards(this);
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java b/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
index 212b6be..8e59f46 100644
--- a/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
+++ b/src/com/android/settings/homepage/contextualcards/ControllerRendererPool.java
@@ -16,12 +16,14 @@
 
 package com.android.settings.homepage.contextualcards;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.util.Log;
 
 import androidx.collection.ArraySet;
 import androidx.lifecycle.LifecycleOwner;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardController;
 import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
 import com.android.settings.homepage.contextualcards.slices.SliceContextualCardController;
@@ -63,14 +65,32 @@
         return (T) controller;
     }
 
-    public Set<ContextualCardController> getControllers() {
+    @VisibleForTesting
+    Set<ContextualCardController> getControllers() {
         return mControllers;
     }
 
-    public ContextualCardRenderer getRenderer(Context context, LifecycleOwner lifecycleOwner,
-            @ContextualCard.CardType int cardType) {
+    @VisibleForTesting
+    Set<ContextualCardRenderer> getRenderers() {
+        return mRenderers;
+    }
+
+    public ContextualCardRenderer getRendererByViewType(Context context,
+            LifecycleOwner lifecycleOwner, int viewType) {
         final Class<? extends ContextualCardRenderer> clz =
-                ContextualCardLookupTable.getCardRendererClasses(cardType);
+                ContextualCardLookupTable.getCardRendererClassByViewType(viewType);
+        return getRenderer(context, lifecycleOwner, clz);
+    }
+
+    public ContextualCardRenderer getRendererByCardType(Context context,
+            LifecycleOwner lifecycleOwner, @ContextualCard.CardType int cardType) {
+        final Class<? extends ContextualCardRenderer> clz =
+                ContextualCardLookupTable.getCardRendererClassByCardType(cardType);
+        return getRenderer(context, lifecycleOwner, clz);
+    }
+
+    private ContextualCardRenderer getRenderer(Context context, LifecycleOwner lifecycleOwner,
+            @NonNull Class<? extends ContextualCardRenderer> clz) {
         for (ContextualCardRenderer renderer : mRenderers) {
             if (renderer.getClass() == clz) {
                 Log.d(TAG, "Renderer is already there.");
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 59c9ba9..c736c4d 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -26,7 +26,6 @@
 import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
 import com.android.settings.wifi.WifiSlice;
 
-import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardCategory;
 import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
 
 /** Provides dynamic card for SettingsIntelligence. */
@@ -41,19 +40,19 @@
                 ContextualCard.newBuilder()
                         .setSliceUri(WifiSlice.WIFI_URI.toString())
                         .setCardName(KEY_WIFI)
-                        .setCategory(ContextualCardCategory.IMPORTANT)
+                        .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCard batteryInfoCard =
                 ContextualCard.newBuilder()
                         .setSliceUri(BatterySlice.BATTERY_CARD_URI.toString())
                         .setCardName(BatterySlice.PATH_BATTERY_INFO)
-                        .setCategory(ContextualCardCategory.DEFAULT)
+                        .setCardCategory(ContextualCard.Category.DEFAULT)
                         .build();
         final ContextualCard connectedDeviceCard =
                 ContextualCard.newBuilder()
                         .setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI.toString())
                         .setCardName(ConnectedDeviceSlice.PATH_CONNECTED_DEVICE)
-                        .setCategory(ContextualCardCategory.IMPORTANT)
+                        .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
         final ContextualCardList cards = ContextualCardList.newBuilder()
                 .addCard(wifiCard)
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java
index b6bb05a..f33633e 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/AirplaneModeConditionController.java
@@ -79,6 +79,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_airplane_title).toString())
                 .setSummaryText(mAppContext.getText(R.string.condition_airplane_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_airplanemode_active))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java
index 8b0ee42..4e40556 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/BackgroundDataConditionController.java
@@ -73,6 +73,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_bg_data_title).toString())
                 .setSummaryText(mAppContext.getText(R.string.condition_bg_data_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_data_saver))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
index 66901f3..bce7c5d 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/BatterySaverConditionController.java
@@ -82,6 +82,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_battery_title).toString())
                 .setSummaryText(mAppContext.getText(R.string.condition_battery_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_battery_saver_accent_24dp))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java
index b2fbbcb..05199ba 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/CellularDataConditionController.java
@@ -89,6 +89,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_cellular_title).toString())
                 .setSummaryText(mAppContext.getText(R.string.condition_cellular_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_cellular_off))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
index eb65819..10881d9 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardController.java
@@ -85,6 +85,14 @@
     public void onConditionsChanged() {
         final List<ContextualCard> conditionCards = mConditionManager.getDisplayableCards();
 
+        final boolean isOddNumber = conditionCards.size() % 2 == 1;
+        if (isOddNumber) {
+            final int lastIndex = conditionCards.size() - 1;
+            final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards.get(
+                    lastIndex);
+            conditionCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build());
+        }
+
         if (mListener != null) {
             final Map<Integer, List<ContextualCard>> conditionalCards = new ArrayMap<>();
             conditionalCards.put(ContextualCard.CardType.CONDITIONAL, conditionCards);
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
index 8a3635b..41c540c 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRenderer.java
@@ -37,6 +37,8 @@
  * Card renderer for {@link ConditionalContextualCard}.
  */
 public class ConditionContextualCardRenderer implements ContextualCardRenderer {
+    public static final int HALF_WIDTH_VIEW_TYPE = R.layout.homepage_condition_half_tile;
+    public static final int FULL_WIDTH_VIEW_TYPE = R.layout.homepage_condition_full_tile;
 
     private final Context mContext;
     private final ControllerRendererPool mControllerRendererPool;
@@ -48,8 +50,12 @@
     }
 
     @Override
-    public int getViewType() {
-        return R.layout.homepage_condition_tile;
+    public int getViewType(boolean isHalfWidth) {
+        if (isHalfWidth) {
+            return HALF_WIDTH_VIEW_TYPE;
+        } else {
+            return FULL_WIDTH_VIEW_TYPE;
+        }
     }
 
     @Override
@@ -87,15 +93,12 @@
         view.icon.setImageDrawable(card.getIconDrawable());
         view.title.setText(card.getTitleText());
         view.summary.setText(card.getSummaryText());
-
-        setViewVisibility(view.itemView, R.id.divider, false);
     }
 
     private void initializeActionButton(ConditionalCardHolder view, ConditionalContextualCard card,
             MetricsFeatureProvider metricsFeatureProvider) {
         final CharSequence action = card.getActionText();
         final boolean hasButtons = !TextUtils.isEmpty(action);
-        setViewVisibility(view.itemView, R.id.buttonBar, hasButtons);
 
         final Button button = view.itemView.findViewById(R.id.first_action);
         if (hasButtons) {
@@ -114,13 +117,6 @@
         }
     }
 
-    private void setViewVisibility(View containerView, int viewId, boolean visible) {
-        View view = containerView.findViewById(viewId);
-        if (view != null) {
-            view.setVisibility(visible ? View.VISIBLE : View.GONE);
-        }
-    }
-
     public static class ConditionalCardHolder extends RecyclerView.ViewHolder {
 
         public final ImageView icon;
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
index 21cb6c0..706b50e 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/DndConditionCardController.java
@@ -100,6 +100,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_zen_title).toString())
                 .setSummaryText(getSummary().toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java
index eec7e4a..862f828 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/HotspotConditionController.java
@@ -99,6 +99,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_hotspot_title).toString())
                 .setSummaryText(getSummary().toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_hotspot))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java
index d8d5f79..249e4a0 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/NightDisplayConditionController.java
@@ -78,6 +78,7 @@
                 .setSummaryText(
                         mAppContext.getText(R.string.condition_night_display_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_settings_night_display))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java
index 75a72fd..09b75eb 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/RingerMutedConditionController.java
@@ -72,6 +72,7 @@
                 .setSummaryText(
                         mAppContext.getText(R.string.condition_device_muted_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_notifications_off_24dp))
+                .setIsHalfWidth(true)
                 .build();
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java
index 4c355a3..d8084b5 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/RingerVibrateConditionController.java
@@ -60,6 +60,7 @@
                 .setSummaryText(
                         mAppContext.getText(R.string.condition_device_vibrate_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_volume_ringer_vibrate))
+                .setIsHalfWidth(true)
                 .build();
     }
 }
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java
index c508403f..44b21bf 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/WorkModeConditionController.java
@@ -93,6 +93,7 @@
                 .setTitleText(mAppContext.getText(R.string.condition_work_title).toString())
                 .setSummaryText(mAppContext.getText(R.string.condition_work_summary).toString())
                 .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_signal_workmode_enable))
+                .setIsHalfWidth(true)
                 .build();
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index c2bf536..5fc4473 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -45,6 +45,7 @@
  */
 public class SliceContextualCardRenderer implements ContextualCardRenderer,
         SliceView.OnSliceActionListener {
+    public static final int VIEW_TYPE = R.layout.homepage_slice_tile;
 
     private static final String TAG = "SliceCardRenderer";
 
@@ -61,8 +62,8 @@
     }
 
     @Override
-    public int getViewType() {
-        return R.layout.homepage_slice_tile;
+    public int getViewType(boolean isHalfWidth) {
+        return VIEW_TYPE;
     }
 
     @Override
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index b2eb8bb..9c1f07c 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -25,9 +25,11 @@
 import android.content.Intent;
 import android.provider.Settings;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.Toolbar;
 
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.Utils;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.search.SearchIndexableResources;
 
@@ -64,6 +66,13 @@
         if (activity == null || toolbar == null) {
             return;
         }
+        if (!Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName())) {
+            final ViewGroup parent = (ViewGroup)toolbar.getParent();
+            if (parent != null) {
+                parent.setVisibility(View.GONE);
+            }
+            return;
+        }
         // Please forgive me for what I am about to do.
         //
         // Need to make the navigation icon non-clickable so that the entire card is clickable
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index 81e9e60..0caa308 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -56,9 +56,15 @@
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        final Context context = mHost.getContext();
+        final String SettingsIntelligencePkgName = FeatureFactory.getFactory(context)
+                .getSearchFeatureProvider().getSettingsIntelligencePkgName();
         if (!Utils.isDeviceProvisioned(mHost.getContext())) {
             return;
         }
+        if (!Utils.isPackageEnabled(mHost.getContext(), SettingsIntelligencePkgName)) {
+            return;
+        }
         if (menu == null) {
             return;
         }
@@ -72,10 +78,8 @@
         searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
 
         searchItem.setOnMenuItemClickListener(target -> {
-            final Context context = mHost.getContext();
             final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
-            intent.setPackage(FeatureFactory.getFactory(mHost.getContext())
-                    .getSearchFeatureProvider().getSettingsIntelligencePkgName());
+            intent.setPackage(SettingsIntelligencePkgName);
             FeatureFactory.getFactory(context).getMetricsFeatureProvider()
                     .action(context, MetricsProto.MetricsEvent.ACTION_SEARCH_RESULTS);
             mHost.startActivityForResult(intent, 0 /* requestCode */);
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
index 6b368c5..0de5c77 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettingsForSub.java
@@ -401,6 +401,7 @@
         // Build and return intent
         Intent intent = new Intent();
         intent.setComponent(componentName);
+        intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, mSubId);
         return intent;
     }
 
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index 2afe35b..9f81431 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -67,7 +67,7 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (mWifiConfiguration != null) {
-            //TODO(b/117957974): update MAC randomization level to WifiManager
+            mWifiConfiguration.macRandomizationSetting = Integer.parseInt((String) newValue);
             mWifiManager.updateNetwork(mWifiConfiguration);
         }
         updateSummary((DropDownPreference) preference, Integer.parseInt((String) newValue));
@@ -77,10 +77,9 @@
     @VisibleForTesting
     int getRandomizationValue() {
         if (mWifiConfiguration != null) {
-            //TODO(b/117957974): get real MAC randomization level from WifiManager
-            return 0;
+            return mWifiConfiguration.macRandomizationSetting;
         }
-        return 0;
+        return WifiConfiguration.RANDOMIZATION_PERSISTENT;
     }
 
     private void updateSummary(DropDownPreference preference, int macRandomized) {
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 6f4deca..f9301a2 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -15,7 +15,6 @@
 com.android.settings.applications.AppLaunchSettings
 com.android.settings.applications.AppStorageSettings
 com.android.settings.applications.ConfirmConvertToFbe
-com.android.settings.applications.DirectoryAccessDetails
 com.android.settings.applications.ProcessStatsDetail
 com.android.settings.applications.ProcessStatsSummary
 com.android.settings.applications.ProcessStatsUi
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index af25f48..2c98f70 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -38,6 +38,7 @@
 
 import com.android.settings.core.OnActivityResultListener;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUtils;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,6 +47,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -69,6 +71,7 @@
     }
 
     @Test
+    @Config(shadows = ShadowUtils.class)
     public void onCreate_deviceNotProvisioned_shouldDisableSearch() {
         Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
         final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
@@ -80,6 +83,7 @@
     }
 
     @Test
+    @Config(shadows = ShadowUtils.class)
     public void onCreate_deviceProvisioned_shouldEnableSearch() {
         Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
         final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class)
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 5f2abba..77cbae2 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -93,6 +93,7 @@
         when(mContext.getSystemService(WifiManager.class)).thenReturn(wifiManager);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(connectivityManager);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
     }
 
     @Test
@@ -200,4 +201,27 @@
         verify(mPackageManager).getApplicationInfoAsUser(eq(PACKAGE_NAME), anyInt(), eq(USER_ID));
         verify(mIconDrawableFactory).getBadgedIcon(mApplicationInfo, USER_ID);
     }
+
+    @Test
+    public void isPackageEnabled_appEnabled_returnTrue()
+            throws PackageManager.NameNotFoundException{
+        mApplicationInfo.enabled = true;
+        when(mPackageManager.getApplicationInfo(PACKAGE_NAME, 0)).thenReturn(mApplicationInfo);
+
+        assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isTrue();
+    }
+
+    @Test
+    public void isPackageEnabled_appDisabled_returnTrue()
+            throws PackageManager.NameNotFoundException{
+        mApplicationInfo.enabled = false;
+        when(mPackageManager.getApplicationInfo(PACKAGE_NAME, 0)).thenReturn(mApplicationInfo);
+
+        assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
+    }
+
+    @Test
+    public void isPackageEnabled_noApp_returnFalse() {
+        assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
index a4d1567..2648916 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
@@ -35,8 +35,10 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.os.UserManager;
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.preference.Preference;
@@ -44,9 +46,12 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.dashboard.DashboardFeatureProviderImpl;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowAccountManager;
+import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.Tile;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -54,10 +59,11 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowAccountManager;
+import org.robolectric.shadow.api.Shadow;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowAccountManager.class, ShadowUserManager.class})
 public class AccountDetailDashboardFragmentTest {
 
     private static final String METADATA_CATEGORY = "com.android.settings.category";
@@ -86,6 +92,11 @@
         when(mFragment.getContext()).thenReturn(mContext);
     }
 
+    @After
+    public void tearDown() {
+        ShadowAccountManager.reset();
+    }
+
     @Test
     public void testCategory_isAccountDetail() {
         assertThat(new AccountDetailDashboardFragment().getCategoryKey())
@@ -152,17 +163,45 @@
     }
 
     @Test
-    @Config(shadows = {ShadowAccountManager.class})
     public void onResume_accountMissing_shouldFinish() {
+        ShadowUserManager userManager = Shadow.extract(
+                mContext.getSystemService(UserManager.class));
+        ShadowAccountManager acctMgr = Shadow.extract(
+                mContext.getSystemService(AccountManager.class));
+
+        userManager.addProfile(new UserInfo(1, null, 0));
+        acctMgr.addAccountForUser(1, new Account("test@test.com", "com.test"));
+
         mFragment.finishIfAccountMissing();
         verify(mFragment).finish();
     }
 
     @Test
-    @Config(shadows = {ShadowAccountManager.class})
-    public void onResume_accountPresent_shouldNotFinish() {
-        AccountManager mgr = mContext.getSystemService(AccountManager.class);
-        Shadows.shadowOf(mgr).addAccount(mFragment.mAccount);
+    public void onResume_accountPresentOneProfile_shouldNotFinish() {
+        ShadowUserManager userManager = Shadow.extract(
+                mContext.getSystemService(UserManager.class));
+        ShadowAccountManager acctMgr = Shadow.extract(
+                mContext.getSystemService(AccountManager.class));
+
+        userManager.addProfile(new UserInfo(1, null, 0));
+        acctMgr.addAccountForUser(1, mFragment.mAccount);
+
+        mFragment.finishIfAccountMissing();
+        verify(mFragment, never()).finish();
+    }
+
+    @Test
+    public void onResume_accountPresentTwoProfiles_shouldNotFinish() {
+        ShadowUserManager userManager = Shadow.extract(
+                mContext.getSystemService(UserManager.class));
+        ShadowAccountManager acctMgr = Shadow.extract(
+                mContext.getSystemService(AccountManager.class));
+
+        userManager.addProfile(new UserInfo(1, null, 0));
+        userManager.addProfile(new UserInfo(2, null, 0));
+        acctMgr.addAccountForUser(1, new Account("test@test.com", "com.test"));
+        acctMgr.addAccountForUser(2, mFragment.mAccount);
+
         mFragment.finishIfAccountMissing();
         verify(mFragment, never()).finish();
     }
diff --git a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
index 22c2cdb..241765e 100644
--- a/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/ChooseAccountPreferenceControllerTest.java
@@ -76,7 +76,7 @@
     @After
     public void tearDown() {
         ShadowContentResolver.reset();
-        ShadowAccountManager.resetAuthenticator();
+        ShadowAccountManager.reset();
         ShadowRestrictedLockUtilsInternal.clearDisabledTypes();
     }
 
diff --git a/tests/robotests/src/com/android/settings/gestures/PreventRingingGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PreventRingingGesturePreferenceControllerTest.java
new file mode 100644
index 0000000..6d77d77
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/PreventRingingGesturePreferenceControllerTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.preference.PreferenceCategory;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PreventRingingGesturePreferenceControllerTest {
+
+    private Context mContext;
+    private Resources mResources;
+    private PreventRingingGesturePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mContext = spy(RuntimeEnvironment.application);
+        mResources = mock(Resources.class);
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled))
+                .thenReturn(true);
+        mController = new PreventRingingGesturePreferenceController(mContext, null);
+        mController.mVibratePref = new RadioButtonPreference(mContext);
+        mController.mNonePref = new RadioButtonPreference(mContext);
+        mController.mMutePref = new RadioButtonPreference(mContext);
+    }
+
+    @Test
+    public void testIsAvailable_configIsTrue_shouldReturnTrue() {
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(true);
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void testIsAvailable_configIsFalse_shouldReturnFalse() {
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_mute() {
+        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+                Settings.Secure.VOLUME_HUSH_MUTE);
+        mController.updateState(null);
+        assertThat(mController.mVibratePref.isChecked()).isFalse();
+        assertThat(mController.mNonePref.isChecked()).isFalse();
+        assertThat(mController.mMutePref.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_vibrate() {
+        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+                Settings.Secure.VOLUME_HUSH_VIBRATE);
+        mController.updateState(null);
+        assertThat(mController.mVibratePref.isChecked()).isTrue();
+        assertThat(mController.mNonePref.isChecked()).isFalse();
+        assertThat(mController.mMutePref.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_other() {
+        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+                7);
+        mController.updateState(null);
+        assertThat(mController.mVibratePref.isChecked()).isFalse();
+        assertThat(mController.mNonePref.isChecked()).isTrue();
+        assertThat(mController.mMutePref.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testRadioButtonClicked_mute() {
+        RadioButtonPreference rbPref = new RadioButtonPreference(mContext);
+        rbPref.setKey(PreventRingingGesturePreferenceController.KEY_MUTE);
+
+        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+                Settings.Secure.VOLUME_HUSH_OFF);
+        mController.onRadioButtonClicked(rbPref);
+
+        assertThat(Settings.Secure.VOLUME_HUSH_MUTE).isEqualTo(
+                Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_OFF));
+    }
+
+    @Test
+    public void testRadioButtonClicked_vibrate() {
+        RadioButtonPreference rbPref = new RadioButtonPreference(mContext);
+        rbPref.setKey(PreventRingingGesturePreferenceController.KEY_VIBRATE);
+
+        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+                Settings.Secure.VOLUME_HUSH_OFF);
+        mController.onRadioButtonClicked(rbPref);
+
+        assertThat(Settings.Secure.VOLUME_HUSH_VIBRATE).isEqualTo(
+                Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_OFF));
+    }
+
+    @Test
+    public void testRadioButtonClicked_off() {
+        RadioButtonPreference rbPref = new RadioButtonPreference(mContext);
+        rbPref.setKey(PreventRingingGesturePreferenceController.KEY_NONE);
+
+        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
+                Settings.Secure.VOLUME_HUSH_MUTE);
+
+        mController.onRadioButtonClicked(rbPref);
+
+        assertThat(Settings.Secure.VOLUME_HUSH_OFF).isEqualTo(
+                Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/PreventRingingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PreventRingingPreferenceControllerTest.java
deleted file mode 100644
index 65c3b5d..0000000
--- a/tests/robotests/src/com/android/settings/gestures/PreventRingingPreferenceControllerTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.settings.gestures;
-
-import static android.provider.Settings.Secure.VOLUME_HUSH_GESTURE;
-import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
-import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class PreventRingingPreferenceControllerTest {
-
-    private static final String KEY_PICK_UP = "gesture_prevent_ringing";
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
-    private PreventRingingPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mController = new PreventRingingPreferenceController(mContext, KEY_PICK_UP);
-    }
-
-    @Test
-    public void testIsAvailable_configIsTrue_shouldReturnTrue() {
-        when(mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(true);
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void testIsAvailable_configIsFalse_shouldReturnFalse() {
-        when(mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(false);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void testUpdateState_mute() {
-        ListPreference pref = mock(ListPreference.class);
-        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
-                Settings.Secure.VOLUME_HUSH_MUTE);
-        mController.updateState(pref);
-        verify(pref).setValue(String.valueOf(Settings.Secure.VOLUME_HUSH_MUTE));
-    }
-
-    @Test
-    public void testUpdateState_vibrate() {
-        ListPreference pref = mock(ListPreference.class);
-        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
-                Settings.Secure.VOLUME_HUSH_VIBRATE);
-        mController.updateState(pref);
-        verify(pref).setValue(String.valueOf(Settings.Secure.VOLUME_HUSH_VIBRATE));
-    }
-
-    @Test
-    public void testUpdateState_other() {
-        ListPreference pref = mock(ListPreference.class);
-        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
-                7);
-        mController.updateState(pref);
-        verify(pref).setValue(String.valueOf(Settings.Secure.VOLUME_HUSH_OFF));
-    }
-
-    @Test
-    public void testUpdateState_parentPage() {
-        Preference pref = mock(Preference.class);
-        // verify no exception
-        mController.updateState(pref);
-    }
-
-    @Test
-    public void testOnPreferenceChange() {
-        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.VOLUME_HUSH_GESTURE,
-                7);
-
-        mController.onPreferenceChange(mock(Preference.class), String.valueOf(VOLUME_HUSH_MUTE));
-
-        assertEquals(VOLUME_HUSH_MUTE, Settings.Secure.getInt(mContext.getContentResolver(),
-                VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
index 4ef982f..b25508b 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/CardDatabaseHelperTest.java
@@ -74,6 +74,7 @@
                 CardDatabaseHelper.CardColumns.CARD_ACTION,
                 CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS,
                 CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH,
+                CardDatabaseHelper.CardColumns.CARD_DISMISSED,
         };
 
         assertThat(columnNames).isEqualTo(expectedNames);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTableTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTableTest.java
new file mode 100644
index 0000000..4724500
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLookupTableTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.settings.homepage.contextualcards.ContextualCardLookupTable
+        .ControllerRendererMapping;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ContextualCardLookupTableTest {
+
+    private static final int UNSUPPORTED_CARD_TYPE = -99999;
+    private static final int UNSUPPORTED_VIEW_TYPE = -99999;
+
+    private List<ControllerRendererMapping> mOriginalLookupTable;
+
+    @Before
+    public void setUp() {
+        mOriginalLookupTable = new ArrayList<>();
+        ContextualCardLookupTable.LOOKUP_TABLE.stream()
+                .forEach(mapping -> mOriginalLookupTable.add(mapping));
+    }
+
+    @After
+    public void reset() {
+        ContextualCardLookupTable.LOOKUP_TABLE.clear();
+        ContextualCardLookupTable.LOOKUP_TABLE.addAll(mOriginalLookupTable);
+    }
+
+    @Test
+    public void getCardControllerClass_hasSupportedCardType_shouldGetCorrespondingController() {
+        for (ControllerRendererMapping mapping : ContextualCardLookupTable.LOOKUP_TABLE) {
+            assertThat(ContextualCardLookupTable.getCardControllerClass(mapping.mCardType))
+                    .isEqualTo(mapping.mControllerClass);
+        }
+    }
+
+    @Test
+    public void getCardControllerClass_hasUnsupportedCardType_shouldAlwaysGetNull() {
+        assertThat(ContextualCardLookupTable.getCardControllerClass(UNSUPPORTED_CARD_TYPE))
+                .isNull();
+    }
+
+    @Test
+    public void
+    getCardRendererClassByViewType_hasSupportedViewType_shouldGetCorrespondingRenderer() {
+        for (ControllerRendererMapping mapping : ContextualCardLookupTable.LOOKUP_TABLE) {
+            assertThat(ContextualCardLookupTable.getCardRendererClassByViewType(mapping.mViewType))
+                    .isEqualTo(mapping.mRendererClass);
+        }
+    }
+
+    @Test
+    public void getCardRendererClassByViewType_hasUnsupportedViewType_shouldAlwaysGetNull() {
+        assertThat(ContextualCardLookupTable.getCardRendererClassByViewType(
+                UNSUPPORTED_VIEW_TYPE)).isNull();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void
+    getCardRendererClassByViewType_hasDuplicateViewType_shouldThrowsIllegalStateException() {
+        final ControllerRendererMapping mapping1 =
+                new ControllerRendererMapping(
+                        1111 /* cardType */, UNSUPPORTED_VIEW_TYPE /* viewType */,
+                        ContextualCardController.class, ContextualCardRenderer.class
+                );
+        final ControllerRendererMapping mapping2 =
+                new ControllerRendererMapping(
+                        2222 /* cardType */, UNSUPPORTED_VIEW_TYPE /* viewType */,
+                        ContextualCardController.class, ContextualCardRenderer.class
+                );
+        ContextualCardLookupTable.LOOKUP_TABLE.add(mapping1);
+        ContextualCardLookupTable.LOOKUP_TABLE.add(mapping2);
+
+        ContextualCardLookupTable.getCardRendererClassByViewType(UNSUPPORTED_VIEW_TYPE);
+    }
+
+    @Test
+    public void getRendererClassByCardType_hasSupportedCardType_shouldGetCorrespondingRenderer() {
+        for (ControllerRendererMapping mapping : ContextualCardLookupTable.LOOKUP_TABLE) {
+            assertThat(ContextualCardLookupTable.getCardRendererClassByCardType(mapping.mCardType))
+                    .isEqualTo(mapping.mRendererClass);
+        }
+    }
+
+    @Test
+    public void getCardRendererClassByCardType_hasUnsupportedCardType_shouldAlwaysGetNull() {
+        assertThat(ContextualCardLookupTable.getCardRendererClassByCardType(UNSUPPORTED_CARD_TYPE))
+                .isNull();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ControllerRendererPoolTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ControllerRendererPoolTest.java
new file mode 100644
index 0000000..e51169e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ControllerRendererPoolTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.homepage.contextualcards;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ControllerRendererPoolTest {
+
+    private static final int UNSUPPORTED_CARD_TYPE = -99999;
+    private static final int UNSUPPORTED_VIEW_TYPE = -99999;
+
+    private ControllerRendererPool mPool;
+    private Context mContext;
+    private Lifecycle mLifecycle;
+    private LifecycleOwner mLifecycleOwner;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+
+        mPool = new ControllerRendererPool();
+    }
+
+    @Test
+    public void getController_hasSupportedCardType_shouldReturnCorrespondingController() {
+        ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(mapping -> assertThat(
+                mPool.getController(mContext, mapping.mCardType).getClass()).isEqualTo(
+                mapping.mControllerClass));
+    }
+
+    @Test
+    public void getController_hasSupportedCardType_shouldHaveTwoControllersInPool() {
+        final long count = ContextualCardLookupTable.LOOKUP_TABLE.stream().map(
+                mapping -> mapping.mControllerClass).distinct().count();
+
+        ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(
+                mapping -> mPool.getController(mContext, mapping.mCardType));
+
+        assertThat(mPool.getControllers()).hasSize((int) count);
+    }
+
+    @Test
+    public void getController_hasUnsupportedCardType_shouldReturnNullAndPoolIsEmpty() {
+        final ContextualCardController controller = mPool.getController(mContext,
+                UNSUPPORTED_CARD_TYPE);
+
+        assertThat(controller).isNull();
+        assertThat(mPool.getControllers()).isEmpty();
+    }
+
+    @Test
+    public void getRenderer_hasSupportedViewType_shouldReturnCorrespondingRenderer() {
+        ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(mapping -> assertThat(
+                mPool.getRendererByViewType(mContext, mLifecycleOwner,
+                        mapping.mViewType).getClass()).isEqualTo(mapping.mRendererClass));
+    }
+
+    @Test
+    public void getRenderer_hasSupportedViewType_shouldHaveDistinctRenderersInPool() {
+        final long count = ContextualCardLookupTable.LOOKUP_TABLE.stream().map(
+                mapping -> mapping.mRendererClass).distinct().count();
+
+        ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(
+                mapping -> mPool.getRendererByViewType(mContext, mLifecycleOwner,
+                        mapping.mViewType));
+
+        assertThat(mPool.getRenderers()).hasSize((int) count);
+    }
+
+    @Test
+    public void getRenderer_hasUnsupportedViewType_shouldReturnNullAndPoolIsEmpty() {
+        final ContextualCardRenderer renderer = mPool.getRendererByViewType(mContext,
+                mLifecycleOwner,
+                UNSUPPORTED_VIEW_TYPE);
+
+        assertThat(renderer).isNull();
+        assertThat(mPool.getRenderers()).isEmpty();
+    }
+
+    @Test
+    public void getRenderer_hasSupportedCardTypeAndWidth_shouldReturnCorrespondingRenderer() {
+        ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(mapping -> assertThat(
+                mPool.getRendererByCardType(mContext, mLifecycleOwner,
+                        mapping.mCardType).getClass()).isEqualTo(mapping.mRendererClass));
+    }
+
+    @Test
+    public void getRenderer_hasSupportedCardTypeAndWidth_shouldHaveDistinctRenderersInPool() {
+        final long count = ContextualCardLookupTable.LOOKUP_TABLE.stream().map(
+                mapping -> mapping.mRendererClass).distinct().count();
+
+        ContextualCardLookupTable.LOOKUP_TABLE.stream().forEach(
+                mapping -> mPool.getRendererByCardType(mContext, mLifecycleOwner,
+                        mapping.mCardType));
+
+        assertThat(mPool.getRenderers()).hasSize((int) count);
+    }
+
+    @Test
+    public void getRenderer_hasUnsupportedCardType_shouldReturnNullAndPoolIsEmpty() {
+        final ContextualCardRenderer renderer = mPool.getRendererByCardType(mContext,
+                mLifecycleOwner,
+                UNSUPPORTED_CARD_TYPE);
+
+        assertThat(renderer).isNull();
+        assertThat(mPool.getRenderers()).isEmpty();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
index 8b541c6..6b1f8b1 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -19,7 +19,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.app.slice.SliceManager;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 
@@ -28,30 +33,37 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.wifi.WifiSlice;
 
-import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardCategory;
 import com.google.android.settings.intelligence.libs.contextualcards.ContextualCardProvider;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class SettingsContextualCardProviderTest {
 
+    @Mock
+    private SliceManager mSliceManager;
     private ContentResolver mResolver;
     private Uri mUri;
     private SettingsContextualCardProvider mProvider;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mResolver = RuntimeEnvironment.application.getContentResolver();
         mUri = new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_CONTENT)
                 .authority(SettingsContextualCardProvider.CARD_AUTHORITY)
                 .build();
-        mProvider = Robolectric.setupContentProvider(SettingsContextualCardProvider.class);
+        mProvider = spy(Robolectric.setupContentProvider(SettingsContextualCardProvider.class));
+        final Context context = spy(RuntimeEnvironment.application);
+        doReturn(mSliceManager).when(context).getSystemService(SliceManager.class);
+        doReturn(context).when(mProvider).getContext();
     }
 
     @Test
@@ -59,7 +71,7 @@
         final int actualNo = mProvider.getContextualCards().getCardCount();
 
         final Bundle returnValue =
-                mResolver.call(mUri, ContextualCardProvider.METHOD_GET_CARD_LIST, "", null);
+                mProvider.call(ContextualCardProvider.METHOD_GET_CARD_LIST, "", null);
         final ContextualCardList cards =
                 ContextualCardList.parseFrom(
                         returnValue.getByteArray(ContextualCardProvider.BUNDLE_CARD_LIST));
@@ -76,6 +88,6 @@
             }
         }
 
-        assertThat(wifiCard.getCategory()).isEqualTo(ContextualCardCategory.IMPORTANT);
+        assertThat(wifiCard.getCardCategory()).isEqualTo(ContextualCard.Category.IMPORTANT);
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
index ccfbbfb..376042d 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/ConditionContextualCardRendererTest.java
@@ -61,7 +61,7 @@
 
     @Test
     public void bindView_shouldSetListener() {
-        final int viewType = mRenderer.getViewType();
+        final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
         final RecyclerView recyclerView = new RecyclerView(mContext);
         recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
         final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
@@ -78,7 +78,7 @@
 
     @Test
     public void viewClick_shouldInvokeControllerPrimaryClick() {
-        final int viewType = mRenderer.getViewType();
+        final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
         final RecyclerView recyclerView = new RecyclerView(mContext);
         recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
         final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index 025f262..7a07d35 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -113,7 +113,7 @@
     }
 
     private RecyclerView.ViewHolder getSliceViewHolder() {
-        final int viewType = mRenderer.getViewType();
+        final int viewType = mRenderer.getViewType(false /* isHalfWidth */);
         final RecyclerView recyclerView = new RecyclerView(mContext);
         recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
         final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index ba29ea1..d0546b6 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -29,12 +29,14 @@
 
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
 import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class SearchFeatureProviderImplTest {
@@ -50,6 +52,7 @@
     }
 
     @Test
+    @Config(shadows = ShadowUtils.class)
     public void initSearchToolbar_shouldInitWithOnClickListener() {
         mProvider.initSearchToolbar(mActivity, null);
         // Should not crash.
diff --git a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
index 3ab4ab4..b4076b5 100644
--- a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
@@ -30,6 +30,7 @@
 
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settingslib.core.lifecycle.ObservableFragment;
 import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
 
@@ -39,8 +40,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 @RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowUtils.class)
 public class SearchMenuControllerTest {
 
     @Mock
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
index 03aabb5..4401926 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccountManager.java
@@ -16,19 +16,24 @@
 
 package com.android.settings.testutils.shadow;
 
+import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorDescription;
+import android.annotation.NonNull;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 @Implements(AccountManager.class)
 public class ShadowAccountManager{
 
     private static final Map<String, AuthenticatorDescription> sAuthenticators = new HashMap<>();
+    private static final Map<Integer, List<Account>> sAccountsByUserId = new HashMap<>();
 
     @Implementation
     public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
@@ -39,7 +44,24 @@
         sAuthenticators.put(authenticator.type, authenticator);
     }
 
-    public static void resetAuthenticator() {
+    public static void reset() {
         sAuthenticators.clear();
+        sAccountsByUserId.clear();
+    }
+
+    @Implementation @NonNull
+    public Account[] getAccountsAsUser(int userId) {
+        if (sAccountsByUserId.containsKey(userId)) {
+            return sAccountsByUserId.get(userId).toArray(new Account[0]);
+        } else {
+            return new Account[0];
+        }
+    }
+
+    public static void addAccountForUser(int userId, Account account) {
+        if (!sAccountsByUserId.containsKey(userId)) {
+            sAccountsByUserId.put(userId, new ArrayList<>());
+        }
+        sAccountsByUserId.get(userId).add(account);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index b09bc74..0927956 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
@@ -21,9 +21,13 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 
 import com.android.settings.Utils;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.SearchFeatureProviderImpl;
 
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -102,6 +106,11 @@
         return null;
     }
 
+    @Implementation
+    public static boolean isPackageEnabled(Context context, String packageName) {
+        return true;
+    }
+
     public static void setApplicationLabel(String packageName, String appLabel) {
         if (sAppNameMap == null) {
             sAppNameMap = new HashMap<>();
diff --git a/tests/uitests/assets/search_results_list b/tests/uitests/assets/search_results_list
index a0cc894..a8bf6f5 100644
--- a/tests/uitests/assets/search_results_list
+++ b/tests/uitests/assets/search_results_list
@@ -166,7 +166,6 @@
 Device security;security_category
 Device theme;theme
 Dial pad tones;dial_pad_tones
-Directory access;special_app_directory_access
 Disable Bluetooth A2DP hardware offload;bluetooth_disable_a2dp_hw_offload
 Disable HW overlays;disable_overlays
 Disable USB audio routing;usb_audio
@@ -620,4 +619,4 @@
  ;auto_brightness_video
  ;battery_header
  ;battery_tip
- ;feature_flag_category
\ No newline at end of file
+ ;feature_flag_category