Add storage dashborad page.

Refactor shared dashboard page display logic between storage and
system page.

Bug: 31800690
Test: RunSettingsRoboTests

Change-Id: I7eb86f590b79ab871bdb383fb2f5326790beb193
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 3bec337..62ad337 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -164,6 +164,7 @@
     public static class SystemSettings extends SettingsActivity { /* empty */ }
 
     // Top level categories for new IA
+    public static class StorageDashboardActivity extends SettingsActivity {}
     public static class SystemDashboardActivity extends SettingsActivity {}
     public static class SupportDashboardActivity extends SettingsActivity {}
 
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 9319a22..a049d85 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -87,6 +87,7 @@
 import com.android.settings.deviceinfo.PublicVolumeSettings;
 import com.android.settings.deviceinfo.SimStatus;
 import com.android.settings.deviceinfo.Status;
+import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.deviceinfo.StorageSettings;
 import com.android.settings.display.NightDisplaySettings;
 import com.android.settings.fuelgauge.BatterySaverSettings;
@@ -377,6 +378,7 @@
             ManageDomainUrls.class.getName(),
             AutomaticStorageManagerSettings.class.getName(),
             SupportFragment.class.getName(),
+            StorageDashboardFragment.class.getName(),
             SystemDashboardFragment.class.getName(),
     };
 
diff --git a/src/com/android/settings/core/InstrumentedFragment.java b/src/com/android/settings/core/InstrumentedFragment.java
index 79ba5c7..d416e66 100644
--- a/src/com/android/settings/core/InstrumentedFragment.java
+++ b/src/com/android/settings/core/InstrumentedFragment.java
@@ -36,6 +36,7 @@
     // metrics placeholder value. Only use this for development.
     protected final int PLACEHOLDER_METRIC = 10000;
     protected final int SYSTEM_CATEGORY_FRAGMENT = PLACEHOLDER_METRIC + 1;
+    protected final int STORAGE_CATEGORY_FRAGMENT = PLACEHOLDER_METRIC + 2;
 
     public InstrumentedFragment() {
         // Mixin that logs visibility change for activity.
diff --git a/src/com/android/settings/core/PreferenceController.java b/src/com/android/settings/core/PreferenceController.java
new file mode 100644
index 0000000..55e3394
--- /dev/null
+++ b/src/com/android/settings/core/PreferenceController.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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.core;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+/**
+ * A controller that manages event for preference.
+ */
+public abstract class PreferenceController {
+
+    protected Context mContext;
+
+    public PreferenceController(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Displays preference in this controller.
+     */
+    public abstract void displayPreference(PreferenceScreen screen);
+
+    /**
+     * Handles preference tree click
+     *
+     * @param preference the preference being clicked
+     * @return true if click is handled
+     */
+    public abstract boolean handlePreferenceTreeClick(Preference preference);
+
+
+    /**
+     * Removes preference from screen.
+     */
+    protected final void removePreference(PreferenceScreen screen, String key) {
+        Preference pref = screen.findPreference(key);
+        if (pref != null) {
+            screen.removePreference(pref);
+        }
+    }
+
+}
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProvider.java b/src/com/android/settings/dashboard/DashboardFeatureProvider.java
index bbf5bf1..ede8d81 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProvider.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProvider.java
@@ -36,6 +36,11 @@
     DashboardCategory getTilesForHomepage();
 
     /**
+     * Get tiles (wrapped in {@link DashboardCategory}) for storage category.
+     */
+    DashboardCategory getTilesForStorageCategory();
+
+    /**
      * Get tiles (wrapped in {@link DashboardCategory}) for system category.
      */
     DashboardCategory getTilesForSystemCategory();
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index a41ae18..5a47676 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -53,6 +53,11 @@
     }
 
     @Override
+    public DashboardCategory getTilesForStorageCategory() {
+        return mCategoryManager.getTilesByCategory(mContext, CategoryKey.CATEGORY_STORAGE);
+    }
+
+    @Override
     public DashboardCategory getTilesForSystemCategory() {
         return mCategoryManager.getTilesByCategory(mContext, CategoryKey.CATEGORY_SYSTEM);
     }
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
new file mode 100644
index 0000000..28d153e
--- /dev/null
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 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.dashboard;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.drawer.DashboardCategory;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
+import com.android.settingslib.drawer.Tile;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Base fragment for dashboard style UI containing a list of static and dynamic setting items.
+ */
+public abstract class DashboardFragment extends SettingsPreferenceFragment
+        implements SettingsDrawerActivity.CategoryListener, Indexable {
+
+    private final Map<Class, PreferenceController> mPreferenceControllers =
+            new ArrayMap<>();
+
+    protected DashboardFeatureProvider mDashboardFeatureProvider;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mDashboardFeatureProvider =
+                FeatureFactory.getFactory(context).getDashboardFeatureProvider(context);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        final Activity activity = getActivity();
+        if (activity instanceof SettingsDrawerActivity) {
+            ((SettingsDrawerActivity) activity).addCategoryListener(this);
+        }
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        Collection<PreferenceController> controllers = mPreferenceControllers.values();
+        // Give all controllers a chance to handle click.
+        for (PreferenceController controller : controllers) {
+            if (controller.handlePreferenceTreeClick(preference)) {
+                return true;
+            }
+        }
+        return super.onPreferenceTreeClick(preference);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        final Activity activity = getActivity();
+        if (activity instanceof SettingsDrawerActivity) {
+            ((SettingsDrawerActivity) activity).remCategoryListener(this);
+        }
+    }
+
+    protected <T extends PreferenceController> T getPreferenceController(Class<T> clazz) {
+        PreferenceController controller = mPreferenceControllers.get(clazz);
+        return (T) controller;
+    }
+
+    protected void addPreferenceController(PreferenceController controller) {
+        mPreferenceControllers.put(controller.getClass(), controller);
+    }
+
+    protected final void displayTilesAsPreference(String TAG, PreferenceScreen screen,
+            DashboardCategory category) {
+        final Context context = getContext();
+        List<Tile> tiles = category.tiles;
+        for (Tile tile : tiles) {
+            final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
+            if (TextUtils.isEmpty(key)) {
+                Log.d(TAG, "tile does not contain a key, skipping " + tile);
+                continue;
+            }
+            final Preference pref = new DashboardTilePreference(context);
+            pref.setTitle(tile.title);
+            pref.setKey(key);
+            pref.setSummary(tile.summary);
+            if (tile.icon != null) {
+                pref.setIcon(tile.icon.loadDrawable(context));
+            }
+            if (tile.intent != null) {
+                pref.setIntent(tile.intent);
+            }
+            // Use negated priority for order, because tile priority is based on intent-filter
+            // (larger value has higher priority). However pref order defines smaller value has
+            // higher priority.
+            pref.setOrder(-tile.priority);
+            screen.addPreference(pref);
+        }
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
new file mode 100644
index 0000000..86dc07d
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 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.deviceinfo;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+
+public class ManageStoragePreferenceController extends PreferenceController {
+
+    public static final String KEY_MANAGE_STORAGE = "pref_manage_storage";
+
+    public ManageStoragePreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        if (!isAvailable()) {
+            removePreference(screen, KEY_MANAGE_STORAGE);
+        }
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        return false;
+    }
+
+    /**
+     * Whether a preference should be available on screen.
+     */
+    private boolean isAvailable() {
+        return mContext.getResources().getBoolean(R.bool.config_storage_manager_settings_enabled);
+    }
+}
+
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
new file mode 100644
index 0000000..f32731c
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 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.deviceinfo;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+
+public class StorageDashboardFragment extends DashboardFragment {
+
+    private static final String TAG = "StorageDashboardFrag";
+
+    @Override
+    public int getMetricsCategory() {
+        return STORAGE_CATEGORY_FRAGMENT;
+    }
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        addPreferenceController(new ManageStoragePreferenceController(context));
+    }
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        super.onCreatePreferences(savedInstanceState, rootKey);
+        refreshAllPreferences();
+    }
+
+    @Override
+    public void onCategoriesChanged() {
+        refreshAllPreferences();
+    }
+
+    private void refreshAllPreferences() {
+        PreferenceScreen screen = getPreferenceScreen();
+        if (screen != null) {
+            screen.removeAll();
+        }
+        addPreferencesFromResource(R.xml.storage_dashboard_fragment);
+
+        getPreferenceController(ManageStoragePreferenceController.class)
+                .displayPreference(getPreferenceScreen());
+
+        displayTilesAsPreference(TAG, getPreferenceScreen(),
+                mDashboardFeatureProvider.getTilesForStorageCategory());
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java b/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java
index 406750f..dfab981 100644
--- a/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/SystemUpdatePreferenceController.java
@@ -27,29 +27,27 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.core.PreferenceController;
 
 import java.util.List;
 
 import static android.content.Context.CARRIER_CONFIG_SERVICE;
 
-public class SystemUpdatePreferenceController {
+public class SystemUpdatePreferenceController extends PreferenceController {
 
     private static final String TAG = "SysUpdatePrefContr";
 
     static final String KEY_SYSTEM_UPDATE_SETTINGS = "system_update_settings";
     static final String KEY_UPDATE_SETTING = "additional_system_update_settings";
 
-    private final Context mContext;
     private final UserManager mUm;
 
     public SystemUpdatePreferenceController(Context context, UserManager um) {
-        mContext = context;
+        super(context);
         mUm = um;
     }
 
-    /**
-     * Displays preference in this controller.
-     */
+    @Override
     public void displayPreference(PreferenceScreen screen) {
         if (isAvailable(mContext, KEY_SYSTEM_UPDATE_SETTINGS)) {
             Utils.updatePreferenceToSpecificActivityOrRemove(mContext, screen,
@@ -79,12 +77,7 @@
         }
     }
 
-    /**
-     * Handles preference tree click
-     *
-     * @param preference the preference being clicked
-     * @return true if click is handled
-     */
+    @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (KEY_SYSTEM_UPDATE_SETTINGS.equals(preference.getKey())) {
             CarrierConfigManager configManager =
@@ -114,16 +107,6 @@
     }
 
     /**
-     * Removes preference from screen.
-     */
-    private void removePreference(PreferenceScreen screen, String key) {
-        Preference pref = screen.findPreference(key);
-        if (pref != null) {
-            screen.removePreference(pref);
-        }
-    }
-
-    /**
      * Trigger client initiated action (send intent) on system update
      */
     private void ciActionOnSysUpdate(PersistableBundle b) {
diff --git a/src/com/android/settings/system/SystemDashboardFragment.java b/src/com/android/settings/system/SystemDashboardFragment.java
index 398f9f2..54bd3e6 100644
--- a/src/com/android/settings/system/SystemDashboardFragment.java
+++ b/src/com/android/settings/system/SystemDashboardFragment.java
@@ -15,40 +15,30 @@
  */
 package com.android.settings.system;
 
-import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.UserManager;
 import android.provider.SearchIndexableResource;
-import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
-import android.text.TextUtils;
-import android.util.Log;
 
 import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.dashboard.DashboardFeatureProvider;
-import com.android.settings.dashboard.DashboardTilePreference;
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.deviceinfo.SystemUpdatePreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.SettingsDrawerActivity;
-import com.android.settingslib.drawer.Tile;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class SystemDashboardFragment extends SettingsPreferenceFragment
+
+public class SystemDashboardFragment extends DashboardFragment
         implements SettingsDrawerActivity.CategoryListener, Indexable {
 
     private static final String TAG = "SystemDashboardFrag";
 
-    private DashboardFeatureProvider mDashboardFeatureProvider;
-    private SystemUpdatePreferenceController mSystemUpdatePreferenceController;
-
     @Override
     public int getMetricsCategory() {
         return SYSTEM_CATEGORY_FRAGMENT;
@@ -57,19 +47,8 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        mDashboardFeatureProvider =
-                FeatureFactory.getFactory(context).getDashboardFeatureProvider(context);
-        mSystemUpdatePreferenceController =
-                new SystemUpdatePreferenceController(context, UserManager.get(context));
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        final Activity activity = getActivity();
-        if (activity instanceof SettingsDrawerActivity) {
-            ((SettingsDrawerActivity) activity).addCategoryListener(this);
-        }
+        addPreferenceController(
+                new SystemUpdatePreferenceController(context, UserManager.get(context)));
     }
 
     @Override
@@ -79,22 +58,6 @@
     }
 
     @Override
-    public boolean onPreferenceTreeClick(Preference preference) {
-        final boolean handled =
-                mSystemUpdatePreferenceController.handlePreferenceTreeClick(preference);
-        return handled || super.onPreferenceTreeClick(preference);
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-        final Activity activity = getActivity();
-        if (activity instanceof SettingsDrawerActivity) {
-            ((SettingsDrawerActivity) activity).remCategoryListener(this);
-        }
-    }
-
-    @Override
     public void onCategoriesChanged() {
         refreshAllPreferences();
     }
@@ -108,36 +71,13 @@
             screen.removeAll();
         }
 
-        final Context context = getContext();
-        final DashboardCategory category = mDashboardFeatureProvider.getTilesForSystemCategory();
-        final List<Tile> tiles = category.tiles;
-
         addPreferencesFromResource(R.xml.system_dashboard_fragment);
-        screen = getPreferenceScreen();
-        mSystemUpdatePreferenceController.displayPreference(getPreferenceScreen());
 
-        for (Tile tile : tiles) {
-            final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
-            if (TextUtils.isEmpty(key)) {
-                Log.d(TAG, "tile does not contain a key, skipping " + tile);
-                continue;
-            }
-            final Preference pref = new DashboardTilePreference(context);
-            pref.setTitle(tile.title);
-            pref.setKey(key);
-            pref.setSummary(tile.summary);
-            if (tile.icon != null) {
-                pref.setIcon(tile.icon.loadDrawable(context));
-            }
-            if (tile.intent != null) {
-                pref.setIntent(tile.intent);
-            }
-            // Use negated priority for order, because tile priority is based on intent-filter
-            // (larger value has higher priority). However pref order defines smaller value has
-            // higher priority.
-            pref.setOrder(-tile.priority);
-            screen.addPreference(pref);
-        }
+        getPreferenceController(SystemUpdatePreferenceController.class)
+                .displayPreference(getPreferenceScreen());
+
+        displayTilesAsPreference(TAG, getPreferenceScreen(),
+                mDashboardFeatureProvider.getTilesForSystemCategory());
     }
 
     /**