Merge change 26219 into eclair

* changes:
  Reimplement the settings to use async callbacks
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index a54a59a..2a92dce 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -159,8 +159,7 @@
                     final Cursor c =
                             BrowserBookmarksAdapter.queryBookmarksForUrl(
                                     cr, null, url, true);
-                    new DownloadTouchIcon(cr, c, url)
-                            .execute(mTouchIconUrl);
+                    new DownloadTouchIcon(cr, c, url).execute(mTouchIconUrl);
                 }
                 setResult(RESULT_OK);
             }
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index b93c554..448d332 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -2381,6 +2381,14 @@
             resetLockIcon(url);
             setUrlTitle(url, null);
 
+            // If we start a touch icon load and then load a new page, we don't
+            // want to cancel the current touch icon loader. But, we do want to
+            // create a new one when the touch icon url is known.
+            if (mTouchIconLoader != null) {
+                mTouchIconLoader.mActivity = null;
+                mTouchIconLoader = null;
+            }
+
             ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(false);
             if (errorConsole != null) {
                 errorConsole.clearErrorMessages();
@@ -3148,14 +3156,26 @@
         }
 
         @Override
-        public void onReceivedTouchIconUrl(WebView view, String url) {
+        public void onReceivedTouchIconUrl(WebView view, String url,
+                boolean precomposed) {
             final ContentResolver cr = getContentResolver();
             final Cursor c =
                     BrowserBookmarksAdapter.queryBookmarksForUrl(cr,
                             view.getOriginalUrl(), view.getUrl(), true);
             if (c != null) {
                 if (c.getCount() > 0) {
-                    new DownloadTouchIcon(cr, c, view).execute(url);
+                    // Let precomposed icons take precedence over non-composed
+                    // icons.
+                    if (precomposed && mTouchIconLoader != null) {
+                        mTouchIconLoader.cancel(false);
+                        mTouchIconLoader = null;
+                    }
+                    // Have only one async task at a time.
+                    if (mTouchIconLoader == null) {
+                        mTouchIconLoader = new DownloadTouchIcon(
+                                BrowserActivity.this, cr, c, view);
+                        mTouchIconLoader.execute(url);
+                    }
                 } else {
                     c.close();
                 }
@@ -4369,6 +4389,9 @@
 
     private BroadcastReceiver mPackageInstallationReceiver;
 
+    // AsyncTask for downloading touch icons
+    /* package */ DownloadTouchIcon mTouchIconLoader;
+
     // activity requestCode
     final static int COMBO_PAGE                 = 1;
     final static int DOWNLOAD_PAGE              = 2;
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index f8c80d8..23fcc5a 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -401,8 +401,10 @@
             // an inverse fill so we can punch a hole using the round rect.
             Path path = new Path();
             path.setFillType(Path.FillType.INVERSE_WINDING);
-            path.addRoundRect(new RectF(0, 0, touchIcon.getWidth(),
-                    touchIcon.getHeight()), 8f, 8f, Path.Direction.CW);
+            RectF rect = new RectF(0, 0, touchIcon.getWidth(),
+                    touchIcon.getHeight());
+            rect.inset(1, 1);
+            path.addRoundRect(rect, 8f, 8f, Path.Direction.CW);
 
             // Construct a paint that clears the outside of the rectangle and
             // draw.
diff --git a/src/com/android/browser/DownloadTouchIcon.java b/src/com/android/browser/DownloadTouchIcon.java
index 6662e09..07d2d3a 100644
--- a/src/com/android/browser/DownloadTouchIcon.java
+++ b/src/com/android/browser/DownloadTouchIcon.java
@@ -42,8 +42,11 @@
     private final String mOriginalUrl;
     private final String mUrl;
     private final String mUserAgent;
+    /* package */ BrowserActivity mActivity;
 
-    public DownloadTouchIcon(ContentResolver cr, Cursor c, WebView view) {
+    public DownloadTouchIcon(BrowserActivity activity, ContentResolver cr,
+            Cursor c, WebView view) {
+        mActivity = activity;
         mContentResolver = cr;
         mCursor = c;
         // Store these in case they change.
@@ -53,6 +56,7 @@
     }
 
     public DownloadTouchIcon(ContentResolver cr, Cursor c, String url) {
+        mActivity = null;
         mContentResolver = cr;
         mCursor = c;
         mOriginalUrl = null;
@@ -96,10 +100,24 @@
     }
 
     @Override
+    protected void onCancelled() {
+        if (mCursor != null) {
+            mCursor.close();
+        }
+    }
+
+    @Override
     public void onPostExecute(Bitmap icon) {
-        if (icon == null || mCursor == null) {
+        // Do this first in case the download failed.
+        if (mActivity != null) {
+            // Remove the touch icon loader from the BrowserActivity.
+            mActivity.mTouchIconLoader = null;
+        }
+
+        if (icon == null || mCursor == null || isCancelled()) {
             return;
         }
+
         final ByteArrayOutputStream os = new ByteArrayOutputStream();
         icon.compress(Bitmap.CompressFormat.PNG, 100, os);
         ContentValues values = new ContentValues();