Make tabs in all apps actually filter the list of apps.
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 7d0970b..9764f23 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -22,9 +22,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.PixelFormat;
 import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -58,8 +56,16 @@
 
     private GridView mGrid;
 
+    /** All applications in the system (we might only be showing a subset) */
     private ArrayList<ApplicationInfo> mAllAppsList = new ArrayList<ApplicationInfo>();
 
+    /** Currently visible applications in the grid */
+    private ArrayList<ApplicationInfo> mVisibleAppsList = new ArrayList<ApplicationInfo>();
+
+    public enum AppType { APP, GAME, DOWNLOADED, ALL };
+
+    private AppType mCurrentFilter = AppType.ALL;
+
     // preserve compatibility with 3D all apps:
     //    0.0 -> hidden
     //    1.0 -> shown and opaque
@@ -120,8 +126,7 @@
         setVisibility(View.GONE);
         setSoundEffectsEnabled(false);
 
-        mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
-        mAppsAdapter.setNotifyOnChange(false);
+        mAppsAdapter = new AppsAdapter(getContext(), mVisibleAppsList);
     }
 
     @Override
@@ -255,11 +260,10 @@
     public void setApps(ArrayList<ApplicationInfo> list) {
         mAllAppsList.clear();
         addApps(list);
+        filterApps(mCurrentFilter);
     }
 
     public void addApps(ArrayList<ApplicationInfo> list) {
-//        Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
-
         final int N = list.size();
 
         for (int i=0; i<N; i++) {
@@ -271,11 +275,12 @@
             }
             mAllAppsList.add(index, item);
         }
-        mAppsAdapter.notifyDataSetChanged();
+        filterApps(mCurrentFilter);
     }
 
     public void removeApps(ArrayList<ApplicationInfo> list) {
         final int N = list.size();
+
         for (int i=0; i<N; i++) {
             final ApplicationInfo item = list.get(i);
             int index = findAppByComponent(mAllAppsList, item);
@@ -286,7 +291,7 @@
                 // Try to recover.  This should keep us from crashing for now.
             }
         }
-        mAppsAdapter.notifyDataSetChanged();
+        filterApps(mCurrentFilter);
     }
 
     public void updateApps(ArrayList<ApplicationInfo> list) {
@@ -295,6 +300,33 @@
         addApps(list);
     }
 
+    public void filterApps(AppType appType) {
+        mCurrentFilter = appType;
+
+        mAppsAdapter.setNotifyOnChange(false);
+        mVisibleAppsList.clear();
+        if (appType == AppType.ALL) {
+            mVisibleAppsList.addAll(mAllAppsList);
+        } else {
+            int searchFlags = 0;
+
+            if (appType == AppType.APP) {
+                searchFlags = ApplicationInfo.APP_FLAG;
+            } else if (appType == AppType.GAME) {
+                searchFlags = ApplicationInfo.GAME_FLAG;
+            } else if (appType == AppType.DOWNLOADED) {
+                searchFlags = ApplicationInfo.DOWNLOADED_FLAG;
+            }
+
+            for (ApplicationInfo info : mAllAppsList) {
+                if ((info.flags & searchFlags) != 0) {
+                    mVisibleAppsList.add(info);
+                }
+            }
+        }
+        mAppsAdapter.notifyDataSetChanged();
+    }
+
     private static int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
         ComponentName component = item.intent.getComponent();
         final int N = list.size();
diff --git a/src/com/android/launcher2/AllAppsList.java b/src/com/android/launcher2/AllAppsList.java
index e5d8782..4c9bc5e 100644
--- a/src/com/android/launcher2/AllAppsList.java
+++ b/src/com/android/launcher2/AllAppsList.java
@@ -91,7 +91,7 @@
 
         if (matches.size() > 0) {
             for (ResolveInfo info : matches) {
-                add(new ApplicationInfo(info, mIconCache));
+                add(new ApplicationInfo(context.getPackageManager(), info, mIconCache));
             }
         }
     }
@@ -142,7 +142,7 @@
                         info.activityInfo.applicationInfo.packageName,
                         info.activityInfo.name);
                 if (applicationInfo == null) {
-                    add(new ApplicationInfo(info, mIconCache));
+                    add(new ApplicationInfo(context.getPackageManager(), info, mIconCache));
                 } else {
                     mIconCache.remove(applicationInfo.componentName);
                     mIconCache.getTitleAndIcon(applicationInfo, info);
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index 7f6f63f..2002703 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -34,16 +34,23 @@
 
     private static final String TAG = "Launcher.AllAppsTabbed";
 
-    private AllAppsView mAllApps2D;
+    private static final String TAG_ALL = "ALL";
+    private static final String TAG_APPS = "APPS";
+    private static final String TAG_GAMES = "GAMES";
+    private static final String TAG_DOWNLOADED = "DOWNLOADED";
+
+    private AllApps2D mAllApps2D;
+    private Context mContext;
 
     public AllAppsTabbed(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mContext = context;
     }
 
     @Override
     protected void onFinishInflate() {
         try {
-            mAllApps2D = (AllAppsView)findViewById(R.id.all_apps_2d);
+            mAllApps2D = (AllApps2D)findViewById(R.id.all_apps_2d);
             if (mAllApps2D == null) throw new Resources.NotFoundException();
         } catch (Resources.NotFoundException e) {
             Log.e(TAG, "Can't find necessary layout elements for AllAppsTabbed");
@@ -53,15 +60,36 @@
         // This lets us share the same view between all tabs
         TabContentFactory contentFactory = new TabContentFactory() {
             public View createTabContent(String tag) {
-                return (View)mAllApps2D;
+                return mAllApps2D;
             }
         };
 
-        // TODO: Make these tabs show the appropriate content (they're no-ops for now)
-        addTab(newTabSpec("apps").setIndicator("All").setContent(contentFactory));
-        addTab(newTabSpec("apps").setIndicator("Apps").setContent(contentFactory));
-        addTab(newTabSpec("apps").setIndicator("Games").setContent(contentFactory));
-        addTab(newTabSpec("apps").setIndicator("Downloaded").setContent(contentFactory));
+        String label = mContext.getString(R.string.all_apps_tab_all);
+        addTab(newTabSpec(TAG_ALL).setIndicator(label).setContent(contentFactory));
+
+        label = mContext.getString(R.string.all_apps_tab_apps);
+        addTab(newTabSpec(TAG_APPS).setIndicator(label).setContent(contentFactory));
+
+        label = mContext.getString(R.string.all_apps_tab_games);
+        addTab(newTabSpec(TAG_GAMES).setIndicator(label).setContent(contentFactory));
+
+        label = mContext.getString(R.string.all_apps_tab_downloaded);
+        addTab(newTabSpec(TAG_DOWNLOADED).setIndicator(label).setContent(contentFactory));
+
+        setOnTabChangedListener(new OnTabChangeListener() {
+            public void onTabChanged(String tabId) {
+                String tag = getCurrentTabTag();
+                if (tag == TAG_ALL) {
+                    mAllApps2D.filterApps(AllApps2D.AppType.ALL);
+                } else if (tag == TAG_APPS) {
+                    mAllApps2D.filterApps(AllApps2D.AppType.APP);
+                } else if (tag == TAG_GAMES) {
+                    mAllApps2D.filterApps(AllApps2D.AppType.GAME);
+                } else if (tag == TAG_DOWNLOADED) {
+                    mAllApps2D.filterApps(AllApps2D.AppType.DOWNLOADED);
+                }
+            }
+        });
 
         setCurrentTab(0);
         setVisibility(GONE);
@@ -125,5 +153,4 @@
     public void surrender() {
         mAllApps2D.surrender();
     }
-
 }
diff --git a/src/com/android/launcher2/ApplicationInfo.java b/src/com/android/launcher2/ApplicationInfo.java
index 7b00f4f..6d78a44 100644
--- a/src/com/android/launcher2/ApplicationInfo.java
+++ b/src/com/android/launcher2/ApplicationInfo.java
@@ -16,18 +16,21 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.util.Log;
 
+import java.util.ArrayList;
+
 /**
  * Represents an app in AllAppsView.
  */
 class ApplicationInfo extends ItemInfo {
+    private static final String TAG = "Launcher2.ApplicationInfo";
 
     /**
      * The application name.
@@ -51,6 +54,10 @@
 
     ComponentName componentName;
 
+    static final int APP_FLAG = 1;
+    static final int GAME_FLAG = 2;
+    static final int DOWNLOADED_FLAG = 4;
+    int flags = 0;
 
     ApplicationInfo() {
         itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
@@ -59,15 +66,32 @@
     /**
      * Must not hold the Context.
      */
-    public ApplicationInfo(ResolveInfo info, IconCache iconCache) {
-        this.componentName = new ComponentName(
-                info.activityInfo.applicationInfo.packageName,
-                info.activityInfo.name);
+    public ApplicationInfo(PackageManager pm, ResolveInfo info, IconCache iconCache) {
+        final String packageName = info.activityInfo.applicationInfo.packageName;
 
+        this.componentName = new ComponentName(packageName, info.activityInfo.name);
         this.container = ItemInfo.NO_ID;
         this.setActivity(componentName,
                 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
 
+        try {
+            int appFlags = pm.getApplicationInfo(packageName, 0).flags;
+            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
+                flags |= DOWNLOADED_FLAG;
+            }
+            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+                flags |= DOWNLOADED_FLAG;
+            }
+            // TODO: Figure out how to determine what is a game
+
+            // If it's not a game, it's an app
+            if ((flags & GAME_FLAG) == 0) {
+                flags |= APP_FLAG;
+            }
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, "PackageManager.getApplicationInfo failed for " + packageName);
+        }
+
         iconCache.getTitleAndIcon(this, info);
     }
     
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 238fbdf..45cef43 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -1213,7 +1213,7 @@
                 startIndex = i;
                 for (int j=0; i<N && j<batchSize; j++) {
                     // This builds the icon bitmaps.
-                    mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
+                    mAllAppsList.add(new ApplicationInfo(packageManager, apps.get(i), mIconCache));
                     i++;
                 }