Merge "Add a better app filtering mechanism and filter widgets" into jb-ub-now-indigo-rose
diff --git a/res/values/config.xml b/res/values/config.xml
index 8718f15..0766d76 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -81,4 +81,9 @@
 
     <!-- Memory debugging, including a memory dump icon -->
     <bool name="debug_memory_enabled">false</bool>
+
+    <!-- Name of a subclass of com.android.launcher3.AppFilter used to
+         filter the activities shown in the launcher. Can be empty. -->
+    <string name="app_filter_class" translatable="false"></string>
+
 </resources>
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index 5d3aa3a..d955e4e 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -46,11 +46,14 @@
 
     private IconCache mIconCache;
 
+    private AppFilter mAppFilter;
+
     /**
      * Boring constructor.
      */
-    public AllAppsList(IconCache iconCache) {
+    public AllAppsList(IconCache iconCache, AppFilter appFilter) {
         mIconCache = iconCache;
+        mAppFilter = appFilter;
     }
 
     /**
@@ -60,13 +63,16 @@
      * If the app is already in the list, doesn't add it.
      */
     public void add(AppInfo info) {
+        if (mAppFilter != null && !mAppFilter.shouldShowApp(info.componentName)) {
+            return;
+        }
         if (findActivity(data, info.componentName)) {
             return;
         }
         data.add(info);
         added.add(info);
     }
-    
+
     public void clear() {
         data.clear();
         // TODO: do we clear these too?
diff --git a/src/com/android/launcher3/AppFilter.java b/src/com/android/launcher3/AppFilter.java
new file mode 100644
index 0000000..e01436d
--- /dev/null
+++ b/src/com/android/launcher3/AppFilter.java
@@ -0,0 +1,35 @@
+package com.android.launcher3;
+
+import android.content.ComponentName;
+import android.text.TextUtils;
+import android.util.Log;
+
+public abstract class AppFilter {
+
+    private static final boolean DBG = false;
+    private static final String TAG = "AppFilter";
+
+    public abstract boolean shouldShowApp(ComponentName app);
+
+    public static AppFilter loadByName(String className) {
+        if (TextUtils.isEmpty(className)) return null;
+        if (DBG) Log.d(TAG, "Loading AppFilter: " + className);
+        try {
+            Class<?> cls = Class.forName(className);
+            return (AppFilter) cls.newInstance();
+        } catch (ClassNotFoundException e) {
+            Log.e(TAG, "Bad AppFilter class", e);
+            return null;
+        } catch (InstantiationException e) {
+            Log.e(TAG, "Bad AppFilter class", e);
+            return null;
+        } catch (IllegalAccessException e) {
+            Log.e(TAG, "Bad AppFilter class", e);
+            return null;
+        } catch (ClassCastException e) {
+            Log.e(TAG, "Bad AppFilter class", e);
+            return null;
+        }
+    }
+
+}
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 4e9d68b..9b35bb5 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -438,6 +438,9 @@
         for (Object o : widgetsAndShortcuts) {
             if (o instanceof AppWidgetProviderInfo) {
                 AppWidgetProviderInfo widget = (AppWidgetProviderInfo) o;
+                if (!app.shouldShowAppOrWidgetProvider(widget.provider)) {
+                    continue;
+                }
                 widget.label = widget.label.trim();
                 if (widget.minWidth > 0 && widget.minHeight > 0) {
                     // Ensure that all widgets we show can be added on a workspace of this size
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 681ed24..f3a02b3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3937,11 +3937,6 @@
         }
     }
 
-    @Override
-    public boolean shouldShowApp(ResolveInfo app) {
-        return true;
-    }
-
     /**
      * A package was updated.
      *
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index ed96310..7da1c2a 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -34,6 +34,7 @@
 
     private LauncherModel mModel;
     private IconCache mIconCache;
+    private AppFilter mAppFilter;
     private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
     private boolean mIsScreenLarge;
     private float mScreenDensity;
@@ -81,7 +82,9 @@
 
         mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
         mIconCache = new IconCache(sContext);
-        mModel = new LauncherModel(this, mIconCache);
+
+        mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
+        mModel = new LauncherModel(this, mIconCache, mAppFilter);
 
         // Register intent receivers
         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
@@ -147,6 +150,10 @@
         return mModel;
     }
 
+    boolean shouldShowAppOrWidgetProvider(ComponentName componentName) {
+        return mAppFilter == null || mAppFilter.shouldShowApp(componentName);
+    }
+
     WidgetPreviewLoader.CacheDb getWidgetPreviewCacheDb() {
         return mWidgetPreviewCacheDb;
     }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index cc89d01..edfc070 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -158,7 +158,6 @@
         public void bindFolders(HashMap<Long,FolderInfo> folders);
         public void finishBindingItems(boolean upgradePath);
         public void bindAppWidget(LauncherAppWidgetInfo info);
-        public boolean shouldShowApp(ResolveInfo app);
         public void bindAllApplications(ArrayList<AppInfo> apps);
         public void bindAppsAdded(ArrayList<Long> newScreens,
                                   ArrayList<ItemInfo> addNotAnimated,
@@ -179,12 +178,12 @@
         public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);
     }
 
-    LauncherModel(LauncherAppState app, IconCache iconCache) {
+    LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
         final Context context = app.getContext();
 
         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
         mApp = app;
-        mBgAllAppsList = new AllAppsList(iconCache);
+        mBgAllAppsList = new AllAppsList(iconCache, appFilter);
         mIconCache = iconCache;
 
         mDefaultIcon = Utilities.createIconBitmap(
@@ -2397,11 +2396,9 @@
             // Create the ApplicationInfos
             for (int i = 0; i < apps.size(); i++) {
                 ResolveInfo app = apps.get(i);
-                if (oldCallbacks.shouldShowApp(app)) {
-                    // This builds the icon bitmaps.
-                    mBgAllAppsList.add(new AppInfo(packageManager, app,
-                            mIconCache, mLabelCache));
-                }
+                // This builds the icon bitmaps.
+                mBgAllAppsList.add(new AppInfo(packageManager, app,
+                        mIconCache, mLabelCache));
             }
 
             // Huh? Shouldn't this be inside the Runnable below?