Prevent NPE in Launcher when an icon cannot be found.
Bug #2509023

Change-Id: I053c7c9a37ed4aeb4d78a9f62dfdeea09a3959aa
diff --git a/src/com/android/launcher2/FastBitmapDrawable.java b/src/com/android/launcher2/FastBitmapDrawable.java
index 850535e..226d6d8 100644
--- a/src/com/android/launcher2/FastBitmapDrawable.java
+++ b/src/com/android/launcher2/FastBitmapDrawable.java
@@ -24,9 +24,17 @@
 
 class FastBitmapDrawable extends Drawable {
     private Bitmap mBitmap;
+    private int mWidth;
+    private int mHeight;
 
     FastBitmapDrawable(Bitmap b) {
         mBitmap = b;
+        if (b != null) {
+            mWidth = mBitmap.getWidth();
+            mHeight = mBitmap.getHeight();
+        } else {
+            mWidth = mHeight = 0;
+        }
     }
 
     @Override
@@ -49,26 +57,32 @@
 
     @Override
     public int getIntrinsicWidth() {
-        return mBitmap.getWidth();
+        return mWidth;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return mBitmap.getHeight();
+        return mHeight;
     }
 
     @Override
     public int getMinimumWidth() {
-        return mBitmap.getWidth();
+        return mWidth;
     }
 
     @Override
     public int getMinimumHeight() {
-        return mBitmap.getHeight();
+        return mHeight;
     }
 
     public void setBitmap(Bitmap b) {
         mBitmap = b;
+        if (b != null) {
+            mWidth = mBitmap.getWidth();
+            mHeight = mBitmap.getHeight();
+        } else {
+            mWidth = mHeight = 0;
+        }
     }
 
     public Bitmap getBitmap() {
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 855d914..04762e9 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -17,27 +17,14 @@
 package com.android.launcher2;
 
 import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Intent;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.database.Cursor;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.net.Uri;
-import android.util.Log;
-import android.os.Process;
 
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 
 /**
  * Cache of application icons.  Icons can be made from any thread.
@@ -53,9 +40,10 @@
         public Bitmap titleBitmap;
     }
 
-    private LauncherApplication mContext;
-    private PackageManager mPackageManager;
-    private Utilities.BubbleText mBubble;
+    private final Bitmap mDefaultIcon;
+    private final LauncherApplication mContext;
+    private final PackageManager mPackageManager;
+    private final Utilities.BubbleText mBubble;
     private final HashMap<ComponentName, CacheEntry> mCache =
             new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
 
@@ -63,6 +51,18 @@
         mContext = context;
         mPackageManager = context.getPackageManager();
         mBubble = new Utilities.BubbleText(context);
+        mDefaultIcon = makeDefaultIcon();
+    }
+
+    private Bitmap makeDefaultIcon() {
+        Drawable d = mPackageManager.getDefaultActivityIcon();
+        Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1),
+                Math.max(d.getIntrinsicHeight(), 1),
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        d.setBounds(0, 0, b.getWidth(), b.getHeight());
+        d.draw(c);
+        return b;
     }
 
     /**
@@ -90,7 +90,7 @@
         synchronized (mCache) {
             CacheEntry entry = cacheLocked(application.componentName, info);
             if (entry.titleBitmap == null) {
-                entry.titleBitmap = mBubble.createTextBitmap(entry.title.toString());
+                entry.titleBitmap = mBubble.createTextBitmap(entry.title);
             }
 
             application.title = entry.title;
@@ -104,7 +104,7 @@
         ComponentName component = intent.getComponent();
 
         if (resolveInfo == null || component == null) {
-            return null;
+            return mDefaultIcon;
         }
 
         CacheEntry entry = cacheLocked(component, resolveInfo);
@@ -137,4 +137,3 @@
         return entry;
     }
 }
-