Merge "DO NOT MERGE" into eclair
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index c3817fb..8ac915c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1518,7 +1518,7 @@
             } else if (mViewportWidth > 0) {
                 width = Math.max(w, mViewportWidth);
             } else {
-                width = Math.max(w, textwrapWidth);
+                width = textwrapWidth;
             }
         }
         nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
diff --git a/docs/html/resources/community-groups.jd b/docs/html/resources/community-groups.jd
index 61fbcc8..a36a425 100644
--- a/docs/html/resources/community-groups.jd
+++ b/docs/html/resources/community-groups.jd
@@ -1,43 +1,65 @@
 community=true
-page.title=Android Developer Groups
+page.title=Developer Forums
 @jd:body
 
-<p>Welcome to the Android developers community! We're glad you're here and invite you to participate in these discussions. Before posting, please read the <a href="http://source.android.com/discuss/android-discussion-groups-charter">Groups Charter</a> that covers the community guidelines.</p>
+<p>Welcome to the Android developers community! We're glad you're here and invite you to participate in discussions with other Android application developers on topics that interest you.</p>
 
-<p class="note"><strong>Note:</strong> If you are seeking discussion about Android source code (not application development),
-then please refer to the <a href="http://source.android.com/discuss">Open Source Project Mailing lists</a>.</p>
+<p>The lists on this page are primarily for discussion about Android application development. If you are seeking discussion about Android source code (not application development), then please refer to the <a href="http://source.android.com/discuss">Open Source Project Mailing lists</a>.</p>
 
 <p style="margin-bottom:.5em"><strong>Contents</strong></p>
 <ol class="toc">
-  <li><a href="#BeforeYouPost">Before you post</a></li>
-  <li><a href="#ApplicationDeveloperLists">Application developer mailing lists</a></li>
-  <li><a href="#UsingEmail">Using email with the mailing lists</a></li>
+  <li><a href="#StackOverflow">Stack Overflow</a> <span class="new">new!</span></li>
+  <li><a href="#MailingLists">Mailing lists</a><ol>
+    <li><a href="#BeforeYouPost">Before you post</a></li>
+    <li><a href="#UsingEmail">Using email with the mailing lists</a></li>
+    <li><a href="#ApplicationDeveloperLists">Application developer mailing lists</a></li>
+  </ol></li>
+  <li><a href="#MarketHelp">Android Market Help Forum</a></li>
 </ol>
 
-<h2 id="BeforeYouPost">Before you post</h2>
+
+<h2 id="StackOverflow">Stack Overflow</h2>
+
+<p><a href="http://stackoverflow.com">Stack Overflow</a> is a collaboratively edited question and answer site for programmers. It's a great place to ask technical questions about developing and maintaining Android applications. The site is especially useful for asking questions with definite answers, but can also be used for discussing best practices.</p>
+
+<p>On the site, questions and answers relating to Android use the <a href="http://stackoverflow.com/questions/tagged/android">'android' tag</a>. You can look for Android topics by adding '<code>[android]</code>' to your search query, or by visiting the tag page at:</p>
+
+<p style="margin-left: 2em"><a href="http://stackoverflow.com/questions/tagged/android">http://stackoverflow.com/questions/tagged/android</a></p>
+
+<p>If you want to ask a question on Stack Overflow, you can use <a href="http://stackoverflow.com/questions/ask">this form</a>. Before submitting the form, make sure to add the 'android' tag so that other Android developers will be able to find your question. As always, before submitting a new question, take a look at the existing topics to see whether another developer has already asked or answered the question.</p>
+
+<p>If you are getting started with Android development, Stack Overflow may be a great location to ask questions about general Java programming or setting up the Eclipse development environment. Simply tag your questions with the <a href="http://stackoverflow.com/questions/tagged/java">Java</a> or <a href="http://stackoverflow.com/questions/tagged/eclipse">Eclipse</a> tags in these cases.</p>
+
+
+<h2 id="MailingLists">Mailing lists</h2>
+
+<p>There are a number of mailing lists, powered by <a href="http://groups.google.com">Google Groups</a>, available for discussing Android application development.</p>
+
+
+<h3 id="BeforeYouPost">Before you post</h3>
 <p>Before writing a post, please try the following:</p>
 
 <ol>
-<li><a href="{@docRoot}resources/faq/index.html">Read the FAQs</a> The most common questions about developing Android applications are addressed in this frequently updated list.</li>
-<li><strong>Type in keywords of your questions in the main Android site's search bar</strong> (such as the one above). This search encompasses all previous discussions, across all groups, as well as the full contents of the site, documentation, and blogs. Chances are good that somebody has run into the same issue before.</li>
-<li><b>Search the mailing list archives</b> to see whether your questions have already been discussed.
+
+<li>Look through the support information available in the 'More' section of this tab. You may find the answer to your question in the <a href="{@docRoot}resources/faq/commontasks.html">Common Tasks</a>, <a href="{@docRoot}resources/faq/troubleshooting.html">Troubleshooting Tips</a>, or <a href="{@docRoot}resources/faq/index.html">FAQs</a> sections.</li>
+<li>Type in keywords of your questions in the main Android site's search bar (such as the one above). This search encompasses all previous discussions, across all groups, as well as the full contents of the site, documentation, and blogs. Chances are good that somebody has run into the same issue before.</li>
   </li>
 </ol>
 
 <p>If you can't find your answer, then we encourage you to address the community.
 As you write your post, please do the following:
 <ol>
-<li><b>Read
-the <a href="http://sites.google.com/a/android.com/opensource/discuss/android-discussion-groups-charter">mailing list charter</a></b> that covers the community guidelines. 
+<li><strong>Read
+the <a href="http://source.android.com/discuss/android-discussion-groups-charter">mailing list charter</a></strong> that covers the community guidelines.
 </li>
-<li><b>Select the most appropriate mailing list for your question</b>. There are several different lists for 
+<li><strong>Select the most appropriate mailing list for your question</strong>. There are several different lists for
 developers, described below.</li>
 <li>
-    <b>Be very clear</b> about your question
+    <strong>Be very clear</strong> about your question
 in the subject -- it helps everyone, both those trying to answer your
 question as well as those who may be looking for information in the
 future.</li>
-<li><b>Give plenty of details</b> in your post to
+<li><strong>Give plenty of details</strong> in your post to
 help others understand your problem. Code or log snippets, as well as
 pointers to screenshots, may also be helpful. For a great guide to
 phrasing your questions, read <a href="http://www.catb.org/%7Eesr/faqs/smart-questions.html">How To Ask Questions The Smart Way</a>.
@@ -45,77 +67,48 @@
 </ol>
 
 
-<h2 id="ApplicationDeveloperLists">Application developer mailing lists</h2>
-<ul>
-<li><b>Android beginners</b> - You're new to Android application development. You want to figure out how to get started with the Android SDK and the basic Android APIs? Start here. This list is open to any discussion around beginner-type questions for developers using the SDK; this is a great way to get up and running with your new application on the Android platform. Ask about getting your development environment set up, get help with the first steps of Android development (your first User Interface, your first permission, your first file on the Android filesystem, your first app on the Android Market...). Be sure to check the archives first before asking new questions. Please avoid advanced subjects, which belong on android-developers, and user questions, which will get a better reception on android-discuss.
-<ul>
-<li>Subscribe using Google Groups:&nbsp;<a href="http://groups.google.com/group/android-beginners">android-beginners</a></li>
-<li>Subscribe via email:&nbsp;<a href="mailto:android-beginners-subscribe@googlegroups.com">android-beginners-subscribe@googlegroups.com</a></li>
-</ul>
-</li>
-
-<li><b>Android developers</b> - You're now an experienced Android application developer. You've grasped the basics of Android app development, you're comfortable using the SDK, now you want to move to advanced topics. Get help here with troubleshooting applications, advice on implementation, and strategies for improving your application's performance and user experience. This is the not the right place to discuss user issues (use android-discuss for that) or beginner questions with the Android SDK (use android-beginners for that).
-<ul>
-<li>Subscribe using Google Groups:&nbsp;<a href="http://groups.google.com/group/android-developers">android-developers</a></li>
-<li>Subscribe via email:&nbsp;<a href="mailto:android-developers-subscribe@googlegroups.com">android-developers-subscribe@googlegroups.com</a></li>
-</ul>
-</li>
-
-<li><b>Android discuss</b> - The "water cooler" of Android discussion. You can discuss just about anything Android-related here, ideas for the Android platform, announcements about your applications, discussions about Android devices, community resources... As long as your discussion is related to Android, it's on-topic here. However, if you have a discussion here that could belong on another list, you are probably not reaching all of your target audience here and may want to consider shifting to a more targeted list.
-<ul>
-<li>Subscribe using Google Groups:&nbsp;<a href="http://groups.google.com/group/android-discuss">android-discuss</a></li>
-<li>Subscribe via email:&nbsp;<a href="mailto:android-discuss-subscribe@googlegroups.com">android-discuss-subscribe@googlegroups.com</a></li>
-</ul>
-</li>
-
-<li><b>Android ndk</b> - A place for discussing the Android NDK and topics related to using native code in Android applications. 
-<ul>
-<li>Subscribe using Google Groups:&nbsp;<a href="http://groups.google.com/group/android-ndk">android-ndk</a></li>
-<li>Subscribe via email:&nbsp;<a href="mailto:android-ndk-subscribe@googlegroups.com">android-ndk-subscribe@googlegroups.com</a></li>
-</ul>
-</li>
-
-<li><b>Android security discuss</b> - A place for open discussion on secure development, emerging security concerns, and best practices for and by android developers. Please don't disclose vulnerabilities directly on this list, you'd be putting all Android users at risk.
-<ul>
-<li>Subscribe using Google Groups:&nbsp;<a href="http://groups.google.com/group/android-security-discuss">android-security-discuss</a></li>
-<li>Subscribe via email:&nbsp;<a href="mailto:android-security-discuss@googlegroups.com">android-security-discuss@googlegroups.com</a></li>
-</ul>
-</li>
-
-<li><b>Android security announce</b> - A low-volume group for security-related announcements by the Android Security Team.
-<ul>
-<li>Subscribe using Google Groups:&nbsp;<a href="http://groups.google.com/group/android-security-announce">android-security-announce</a></li>
-<li>Subscribe via email:&nbsp;<a href="mailto:android-security-announce-subscribe@googlegroups.com">android-security-announce-subscribe@googlegroups.com</a></li>
-</ul>
-</li>
-
-<li><b>Android Market Help Forum</b> - A web-based discussion forum where you can ask questions or report issues relating to Android Market.
-<ul>
-<li>URL:&nbsp;<a href="http://www.google.com/support/forum/p/Android+Market?hl=en">http://www.google.com/support/forum/p/Android+Market?hl=en</a></li>
-</ul>
-</li>
-
-</ul>
-
-
-
-<h2 id="UsingEmail">Using email with the mailing lists</h2>
+<h3 id="UsingEmail">Using email with the mailing lists</h3>
 <p>Instead of using the <a href="http://groups.google.com/">Google Groups</a> site, you can use your email client of choice to participate in the mailing lists.</p>
 <p>To subscribe to a group without using the Google Groups site, use the link under "subscribe via email" in the lists above.</p>
 <p>To set up how you receive mailing list postings by email:</p>
 
 <ol><li>Sign into the group via the Google Groups site. For example, for the android-framework group you would visit <a href="http://groups.google.com/group/android-framework">http://groups.google.com/group/android-framework</a>.</li>
-<li>Click "Edit
-my membership" on the right side.</li>
-<li>Under "How do
-you want to read this group?" select one of the email options. </li>
+<li>Click "Edit my membership" on the right side.</li>
+<li>Under "How do you want to read this group?" select one of the email options.</li>
 </ol>
 
 
+<h3 id="ApplicationDeveloperLists">Application developer mailing lists</h3>
+<ul>
+<li><strong><a href="http://groups.google.com/group/android-developers">android-developers</a></strong>
+(<a href="mailto:android-developers-subscribe@googlegroups.com">subscribe via email</a>)<br>
+You're now an experienced Android application developer. You've grasped the basics of Android app development, you're comfortable using the SDK, now you want to move to advanced topics. Get help here with troubleshooting applications, advice on implementation, and strategies for improving your application's performance and user experience. This is the not the right place to discuss user issues (use android-discuss for that) or beginner questions with the Android SDK (use android-beginners for that).
+</li>
+
+<li><strong><a href="http://groups.google.com/group/android-discuss">android-discuss</a></strong>
+(<a href="mailto:android-discuss-subscribe@googlegroups.com">subscribe via email</a>)<br>
+The "water cooler" of Android discussion. You can discuss just about anything Android-related here, ideas for the Android platform, announcements about your applications, discussions about Android devices, community resources... As long as your discussion is related to Android, it's on-topic here. However, if you have a discussion here that could belong on another list, you are probably not reaching all of your target audience here and may want to consider shifting to a more targeted list.
+</li>
+
+<li><strong><a href="http://groups.google.com/group/android-ndk">android-ndk</a></strong>
+(<a href="mailto:android-ndk-subscribe@googlegroups.com">subscribe via email</a>)<br>
+A place for discussing the Android NDK and topics related to using native code in Android applications.
+</li>
+
+<li><strong><a href="http://groups.google.com/group/android-security-discuss">android-security-discuss</a></strong>
+(<a href="mailto:android-security-discuss-subscribe@googlegroups.com">subscribe via email</a>)<br>
+A place for open discussion on secure development, emerging security concerns, and best practices for and by android developers. Please don't disclose vulnerabilities directly on this list, you'd be putting all Android users at risk.
+</li>
+
+<li><strong><a href="http://groups.google.com/group/android-security-announce">android-security-announce</a></strong>
+(<a href="mailto:android-security-announce-subscribe@googlegroups.com">subscribe via email</a>)<br>
+A low-volume group for security-related announcements by the Android Security Team.
+</li>
+</ul>
 
 
+<h2 id="MarketHelp">Android Market Help Forum</h2>
 
+<p>The <a href="http://www.google.com/support/forum/p/Android+Market">Android Market Help Forum</a> is a web-based discussion forum where you can ask questions or report issues relating to Android Market.</p>
 
-
-
-</div>
+<p style="margin-left: 2em"><a href="http://www.google.com/support/forum/p/Android+Market">http://www.google.com/support/forum/p/Android+Market</a></p>
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index f5c573e..e337e38 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -11,7 +11,7 @@
     </h2>
     <ul>
       <li><a href="<?cs var:toroot ?>resources/community-groups.html">
-            <span class="en">Android Developer Groups</span>
+            <span class="en">Developer Forums</span>
           </a></li>
       <li><a href="<?cs var:toroot ?>resources/community-more.html">
             <span class="en">IRC, Twitter</span>
diff --git a/docs/html/sdk/download.jd b/docs/html/sdk/download.jd
index 47505e6..029de21 100644
--- a/docs/html/sdk/download.jd
+++ b/docs/html/sdk/download.jd
@@ -58,10 +58,8 @@
   <h2>Thank you for downloading the Android SDK!</h2>
   <p>Your download should be underway. If not, <a id="click-download">click here to start the download</a>.</p>
   <p>To set up your Android development environment, please read the guide to
-    <a href="installing.html">Installing the Android SDK</a>.
-    Once you have completed the installation, see the
-    <a href="/guide/index.html">Dev Guide</a> for documentation about
-    developing Android applications.</p>
+    <a href="installing.html">Installing the Android SDK</a> and ensure that your development
+    machine meets the system requirements linked on that page.</p>
 </div>
 
 <script type="text/javascript">
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 262ac8d..d364277 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -107,9 +107,5 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-# Include the subdirectories ====================
-include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk,\
-            java \
-    	))
 
 endif #simulator
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 23888ff..de8df39 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -776,6 +776,17 @@
     glDrawTexfOES(x, y, z, w, h);
 }
 
+static void SC_drawSpriteScreenspaceCropped(float x, float y, float z, float w, float h,
+        float cx0, float cy0, float cx1, float cy1)
+{
+    GET_TLS();
+    rsc->setupCheck();
+
+    GLint crop[4] = {cx0, cy0, cx1, cy1};
+    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+    glDrawTexfOES(x, y, z, w, h);
+}
+
 static void SC_drawSprite(float x, float y, float z, float w, float h)
 {
     GET_TLS();
@@ -1271,6 +1282,8 @@
         "void", "(float x, float y, float z, float w, float h)" },
     { "drawSpriteScreenspace", (void *)&SC_drawSpriteScreenspace,
         "void", "(float x, float y, float z, float w, float h)" },
+    { "drawSpriteScreenspaceCropped", (void *)&SC_drawSpriteScreenspaceCropped,
+        "void", "(float x, float y, float z, float w, float h, float cx0, float cy0, float cx1, float cy1)" },
     { "drawLine", (void *)&SC_drawLine,
         "void", "(float x1, float y1, float z1, float x2, float y2, float z2)" },
     { "drawPoint", (void *)&SC_drawPoint,
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
index cdce488..0f15cb6 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
@@ -32,4 +32,5 @@
     public static final int EVENT_LOG_PDP_NETWORK_DROP = 50109;
     public static final int EVENT_LOG_CDMA_DATA_SETUP_FAILED = 50110;
     public static final int EVENT_LOG_CDMA_DATA_DROP = 50111;
+    public static final int EVENT_LOG_GSM_RAT_SWITCHED = 50112;
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 8140654..3bf76d4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -38,6 +38,7 @@
 import android.provider.Telephony.Intents;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.Config;
@@ -848,6 +849,21 @@
         cellLoc = newCellLoc;
         newCellLoc = tcl;
 
+
+        // Add an event log when network type switched
+        // TODO: we may add filtering to reduce the event logged,
+        // i.e. check preferred network setting, only switch to 2G, etc
+        if (hasNetworkTypeChanged) {
+            int cid = -1;
+            GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+            if (loc != null) cid = loc.getCid();
+            EventLog.List val = new EventLog.List(cid, networkType, newNetworkType);
+            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_GSM_RAT_SWITCHED, val);
+            Log.d(LOG_TAG,
+                    "RAT switched " + networkTypeToString(networkType) + " -> "
+                    + networkTypeToString(newNetworkType) + " at cell " + cid);
+        }
+
         gprsState = newGPRSState;
         networkType = newNetworkType;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader.java
index 8bf7fcc..ad3974c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import java.awt.Paint;
+
 public class BitmapShader extends Shader {
 
     // we hold on just for the GC, since our native counterpart is using it
@@ -31,11 +33,16 @@
     public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) {
         mBitmap = bitmap;
     }
-    
+
     //---------- Custom methods
-    
+
     public Bitmap getBitmap() {
         return mBitmap;
     }
+
+    @Override
+    Paint getJavaPaint() {
+        return null;
+    }
 }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
index 02e3220..c49e11e 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
@@ -125,13 +125,16 @@
         }
 
         Shader shader = paint.getShader();
-        if (shader instanceof LinearGradient) {
-            g.setPaint(((LinearGradient)shader).getPaint());
-        } else {
-            if (mLogger != null && shader != null) {
-                mLogger.warning(String.format(
-                        "Shader '%1$s' is not supported in the Layout Editor.",
-                        shader.getClass().getCanonicalName()));
+        if (shader != null) {
+            java.awt.Paint shaderPaint = shader.getJavaPaint();
+            if (shaderPaint != null) {
+                g.setPaint(shaderPaint);
+            } else {
+                if (mLogger != null) {
+                    mLogger.warning(String.format(
+                            "Shader '%1$s' is not supported in the Layout Editor.",
+                            shader.getClass().getCanonicalName()));
+                }
             }
         }
 
@@ -409,7 +412,7 @@
 
         g.setColor(new Color(color));
 
-        getGraphics2d().fillRect(0, 0, getWidth(), getHeight());
+        g.fillRect(0, 0, getWidth(), getHeight());
 
         g.setComposite(composite);
 
@@ -781,23 +784,25 @@
 
     private final void doDrawRect(int left, int top, int width, int height, Paint paint) {
         // get current graphisc
-        Graphics2D g = getGraphics2d();
+        if (width != 0 && height != 0) {
+            Graphics2D g = getGraphics2d();
 
-        g = getNewGraphics(paint, g);
+            g = getNewGraphics(paint, g);
 
-        Style style = paint.getStyle();
+            Style style = paint.getStyle();
 
-        // draw
-        if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
-            g.fillRect(left, top, width, height);
+            // draw
+            if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
+                g.fillRect(left, top, width, height);
+            }
+
+            if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
+                g.drawRect(left, top, width, height);
+            }
+
+            // dispose Graphics2D object
+            g.dispose();
         }
-
-        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
-            g.drawRect(left, top, width, height);
-        }
-
-        // dispose Graphics2D object
-        g.dispose();
     }
 
     /* (non-Javadoc)
@@ -806,29 +811,31 @@
     @Override
     public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
         // get current graphisc
-        Graphics2D g = getGraphics2d();
+        if (rect.width() != 0 && rect.height() != 0) {
+            Graphics2D g = getGraphics2d();
 
-        g = getNewGraphics(paint, g);
+            g = getNewGraphics(paint, g);
 
-        Style style = paint.getStyle();
+            Style style = paint.getStyle();
 
-        // draw
+            // draw
 
-        int arcWidth = (int)(rx * 2);
-        int arcHeight = (int)(ry * 2);
+            int arcWidth = (int)(rx * 2);
+            int arcHeight = (int)(ry * 2);
 
-        if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
-            g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
-                    arcWidth, arcHeight);
+            if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
+                g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
+                        arcWidth, arcHeight);
+            }
+
+            if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
+                g.drawRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
+                        arcWidth, arcHeight);
+            }
+
+            // dispose Graphics2D object
+            g.dispose();
         }
-
-        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) {
-            g.drawRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
-                    arcWidth, arcHeight);
-        }
-
-        // dispose Graphics2D object
-        g.dispose();
     }
 
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader.java
index 968a597..863d64a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposeShader.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import java.awt.Paint;
+
 /** A subclass of shader that returns the composition of two other shaders, combined by
     an {@link android.graphics.Xfermode} subclass.
 */
@@ -42,5 +44,10 @@
     public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) {
         // FIXME Implement shader
     }
+
+    @Override
+    Paint getJavaPaint() {
+        return null;
+    }
 }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java
index 1a0dc05..38ffed3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient.java
@@ -16,56 +16,298 @@
 
 package android.graphics;
 
-import java.awt.GradientPaint;
-import java.awt.Color;
 import java.awt.Paint;
+import java.awt.PaintContext;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
 
 public class LinearGradient extends Shader {
-    
-    private GradientPaint mGradientPaint;
 
-    /** Create a shader that draws a linear gradient along a line.
-        @param x0           The x-coordinate for the start of the gradient line
-        @param y0           The y-coordinate for the start of the gradient line
-        @param x1           The x-coordinate for the end of the gradient line
-        @param y1           The y-coordinate for the end of the gradient line
-        @param  colors      The colors to be distributed along the gradient line
-        @param  positions   May be null. The relative positions [0..1] of
-                            each corresponding color in the colors array. If this is null,
-                            the the colors are distributed evenly along the gradient line.
-        @param  tile        The Shader tiling mode
-    */
-    public LinearGradient(float x0, float y0, float x1, float y1,
-                          int colors[], float positions[], TileMode tile) {
+    private Paint mJavaPaint;
+
+    /**
+     * Create a shader that draws a linear gradient along a line.
+     *
+     * @param x0 The x-coordinate for the start of the gradient line
+     * @param y0 The y-coordinate for the start of the gradient line
+     * @param x1 The x-coordinate for the end of the gradient line
+     * @param y1 The y-coordinate for the end of the gradient line
+     * @param colors The colors to be distributed along the gradient line
+     * @param positions May be null. The relative positions [0..1] of each
+     *            corresponding color in the colors array. If this is null, the
+     *            the colors are distributed evenly along the gradient line.
+     * @param tile The Shader tiling mode
+     */
+    public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
+            TileMode tile) {
         if (colors.length < 2) {
             throw new IllegalArgumentException("needs >= 2 number of colors");
         }
         if (positions != null && colors.length != positions.length) {
             throw new IllegalArgumentException("color and position arrays must be of equal length");
         }
-        
-        // FIXME implement multi color linear gradient
+
+        if (positions == null) {
+            float spacing = 1.f / (colors.length - 1);
+            positions = new float[colors.length];
+            positions[0] = 0.f;
+            positions[colors.length-1] = 1.f;
+            for (int i = 1; i < colors.length - 1 ; i++) {
+                positions[i] = spacing * i;
+            }
+        }
+
+        mJavaPaint = new MultiPointLinearGradientPaint(x0, y0, x1, y1, colors, positions, tile);
     }
 
-    /** Create a shader that draws a linear gradient along a line.
-        @param x0       The x-coordinate for the start of the gradient line
-        @param y0       The y-coordinate for the start of the gradient line
-        @param x1       The x-coordinate for the end of the gradient line
-        @param y1       The y-coordinate for the end of the gradient line
-        @param  color0  The color at the start of the gradient line.
-        @param  color1  The color at the end of the gradient line.
-        @param  tile    The Shader tiling mode
-    */
-    public LinearGradient(float x0, float y0, float x1, float y1,
-                          int color0, int color1, TileMode tile) {
-        mGradientPaint = new GradientPaint(x0, y0, new Color(color0, true /* hasalpha */),
-                x1,y1, new Color(color1, true /* hasalpha */), tile != TileMode.CLAMP);
+    /**
+     * Create a shader that draws a linear gradient along a line.
+     *
+     * @param x0 The x-coordinate for the start of the gradient line
+     * @param y0 The y-coordinate for the start of the gradient line
+     * @param x1 The x-coordinate for the end of the gradient line
+     * @param y1 The y-coordinate for the end of the gradient line
+     * @param color0 The color at the start of the gradient line.
+     * @param color1 The color at the end of the gradient line.
+     * @param tile The Shader tiling mode
+     */
+    public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
+            TileMode tile) {
+        this(x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/, tile);
     }
-    
-    //---------- Custom Methods
-    
-    public Paint getPaint() {
-        return mGradientPaint;
+
+    // ---------- Custom Methods
+
+    @Override
+    public Paint getJavaPaint() {
+        return mJavaPaint;
+    }
+
+    private static class MultiPointLinearGradientPaint implements Paint {
+        private final static int GRADIENT_SIZE = 100;
+
+        private final float mX0;
+        private final float mY0;
+        private final float mDx;
+        private final float mDy;
+        private final float mDSize2;
+        private final int[] mColors;
+        private final float[] mPositions;
+        private final TileMode mTile;
+        private int[] mGradient;
+
+        public MultiPointLinearGradientPaint(float x0, float y0, float x1, float y1, int colors[],
+                float positions[], TileMode tile) {
+                mX0 = x0;
+                mY0 = y0;
+                mDx = x1 - x0;
+                mDy = y1 - y0;
+                mDSize2 = mDx * mDx + mDy * mDy;
+
+                mColors = colors;
+                mPositions = positions;
+                mTile = tile;
+        }
+
+        public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+                Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
+            prepareColors();
+            return new MultiPointLinearGradientPaintContext(cm, deviceBounds,
+                    userBounds, xform, hints);
+        }
+
+        public int getTransparency() {
+            return TRANSLUCENT;
+        }
+
+        private synchronized void prepareColors() {
+            if (mGradient == null) {
+                // actually create an array with an extra size, so that we can really go
+                // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0
+                mGradient = new int[GRADIENT_SIZE+1];
+
+                int prevPos = 0;
+                int nextPos = 1;
+                for (int i  = 0 ; i <= GRADIENT_SIZE ; i++) {
+                    // compute current position
+                    float currentPos = (float)i/GRADIENT_SIZE;
+                    while (currentPos > mPositions[nextPos]) {
+                        prevPos = nextPos++;
+                    }
+
+                    float percent = (currentPos - mPositions[prevPos]) /
+                            (mPositions[nextPos] - mPositions[prevPos]);
+
+                    mGradient[i] = getColor(mColors[prevPos], mColors[nextPos], percent);
+                }
+            }
+        }
+
+        /**
+         * Returns the color between c1, and c2, based on the percent of the distance
+         * between c1 and c2.
+         */
+        private int getColor(int c1, int c2, float percent) {
+            int a = getChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent);
+            int r = getChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent);
+            int g = getChannel((c1 >>  8) & 0xFF, (c2 >>  8) & 0xFF, percent);
+            int b = getChannel((c1      ) & 0xFF, (c2      ) & 0xFF, percent);
+            return a << 24 | r << 16 | g << 8 | b;
+        }
+
+        /**
+         * Returns the channel value between 2 values based on the percent of the distance between
+         * the 2 values..
+         */
+        private int getChannel(int c1, int c2, float percent) {
+            return c1 + (int)((percent * (c2-c1)) + .5);
+        }
+
+        private class MultiPointLinearGradientPaintContext implements PaintContext {
+
+            private ColorModel mColorModel;
+            private final Rectangle mDeviceBounds;
+            private final Rectangle2D mUserBounds;
+            private final AffineTransform mXform;
+            private final RenderingHints mHints;
+
+            public MultiPointLinearGradientPaintContext(ColorModel cm, Rectangle deviceBounds,
+                    Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
+                mColorModel = cm;
+                // FIXME: so far all this is always the same rect gotten in getRaster with an indentity matrix?
+                mDeviceBounds = deviceBounds;
+                mUserBounds = userBounds;
+                mXform = xform;
+                mHints = hints;
+            }
+
+            public void dispose() {
+            }
+
+            public ColorModel getColorModel() {
+                return mColorModel;
+            }
+
+            public Raster getRaster(int x, int y, int w, int h) {
+                BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+
+                int[] data = new int[w*h];
+
+                if (mDx == 0) { // vertical gradient
+                    // compute first column and copy to all other columns
+                    int index = 0;
+                    for (int iy = 0 ; iy < h ; iy++) {
+                        int color = getColor(iy + y, mY0, mDy);
+                        for (int ix = 0 ; ix < w ; ix++) {
+                            data[index++] = color;
+                        }
+                    }
+                } else if (mDy == 0) { // horizontal
+                    // compute first line in a tmp array and copy to all lines
+                    int[] line = new int[w];
+                    for (int ix = 0 ; ix < w ; ix++) {
+                        line[ix] = getColor(ix + x, mX0, mDx);
+                    }
+
+                    for (int iy = 0 ; iy < h ; iy++) {
+                        System.arraycopy(line, 0, data, iy*w, line.length);
+                    }
+                } else {
+                    int index = 0;
+                    for (int iy = 0 ; iy < h ; iy++) {
+                        for (int ix = 0 ; ix < w ; ix++) {
+                            data[index++] = getColor(ix + x, iy + y);
+                        }
+                    }
+                }
+
+                image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
+
+                return image.getRaster();
+            }
+        }
+
+        /** Returns a color for the easy vertical/horizontal mode */
+        private int getColor(float absPos, float refPos, float refSize) {
+            float pos = (absPos - refPos) / refSize;
+
+            return getIndexFromPos(pos);
+        }
+
+        /**
+         * Returns a color for an arbitrary point.
+         */
+        private int getColor(float x, float y) {
+            // find the x position on the gradient vector.
+            float _x = (mDx*mDy*(y-mY0) + mDy*mDy*mX0 + mDx*mDx*x) / mDSize2;
+            // from it get the position relative to the vector
+            float pos = (float) ((_x - mX0) / mDx);
+
+            return getIndexFromPos(pos);
+        }
+
+        /**
+         * Returns the color based on the position in the gradient.
+         * <var>pos</var> can be anything, even &lt; 0 or &gt; > 1, as the gradient
+         * will use {@link TileMode} value to convert it into a [0,1] value.
+         */
+        private int getIndexFromPos(float pos) {
+            if (pos < 0.f) {
+                switch (mTile) {
+                    case CLAMP:
+                        pos = 0.f;
+                        break;
+                    case REPEAT:
+                        // remove the integer part to stay in the [0,1] range
+                        // careful: this is a negative value, so use ceil instead of floor
+                        pos = pos - (float)Math.ceil(pos);
+                        break;
+                    case MIRROR:
+                        // get the integer and the decimal part
+                        // careful: this is a negative value, so use ceil instead of floor
+                        int intPart = (int)Math.ceil(pos);
+                        pos = pos - intPart;
+                        // 0  -> -1 : mirrored order
+                        // -1 -> -2: normal order
+                        // etc..
+                        // this means if the intpart is even we invert
+                        if ((intPart % 2) == 0) {
+                            pos = 1.f - pos;
+                        }
+                        break;
+                }
+            } else if (pos > 1f) {
+                switch (mTile) {
+                    case CLAMP:
+                        pos = 1.f;
+                        break;
+                    case REPEAT:
+                        // remove the integer part to stay in the [0,1] range
+                        pos = pos - (float)Math.floor(pos);
+                        break;
+                    case MIRROR:
+                        // get the integer and the decimal part
+                        int intPart = (int)Math.floor(pos);
+                        pos = pos - intPart;
+                        // 0 -> 1 : normal order
+                        // 1 -> 2: mirrored
+                        // etc..
+                        // this means if the intpart is odd we invert
+                        if ((intPart % 2) == 1) {
+                            pos = 1.f - pos;
+                        }
+                        break;
+                }
+            }
+
+            int index = (int)((pos * GRADIENT_SIZE) + .5);
+
+            return mGradient[index];
+        }
     }
 }
-
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java
index f3af133..312dab3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint.java
@@ -59,23 +59,14 @@
     private final FontRenderContext mFontContext = new FontRenderContext(
             new AffineTransform(), true, true);
 
-    @SuppressWarnings("hiding")
     public static final int ANTI_ALIAS_FLAG       = _Original_Paint.ANTI_ALIAS_FLAG;
-    @SuppressWarnings("hiding")
     public static final int FILTER_BITMAP_FLAG    = _Original_Paint.FILTER_BITMAP_FLAG;
-    @SuppressWarnings("hiding")
     public static final int DITHER_FLAG           = _Original_Paint.DITHER_FLAG;
-    @SuppressWarnings("hiding")
     public static final int UNDERLINE_TEXT_FLAG   = _Original_Paint.UNDERLINE_TEXT_FLAG;
-    @SuppressWarnings("hiding")
     public static final int STRIKE_THRU_TEXT_FLAG = _Original_Paint.STRIKE_THRU_TEXT_FLAG;
-    @SuppressWarnings("hiding")
     public static final int FAKE_BOLD_TEXT_FLAG   = _Original_Paint.FAKE_BOLD_TEXT_FLAG;
-    @SuppressWarnings("hiding")
     public static final int LINEAR_TEXT_FLAG      = _Original_Paint.LINEAR_TEXT_FLAG;
-    @SuppressWarnings("hiding")
     public static final int SUBPIXEL_TEXT_FLAG    = _Original_Paint.SUBPIXEL_TEXT_FLAG;
-    @SuppressWarnings("hiding")
     public static final int DEV_KERN_TEXT_FLAG    = _Original_Paint.DEV_KERN_TEXT_FLAG;
 
     public static class FontMetrics extends _Original_Paint.FontMetrics {
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
index 61b693a..13848c5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import java.awt.Paint;
+
 public class RadialGradient extends Shader {
 
    /** Create a shader that draws a radial gradient given the center and radius.
@@ -58,5 +60,11 @@
        }
        // FIXME Implement shader
    }
+
+    @Override
+    Paint getJavaPaint() {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader.java b/tools/layoutlib/bridge/src/android/graphics/Shader.java
index 3a9fda5..0cc5940 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader.java
@@ -16,14 +16,16 @@
 
 package android.graphics;
 
+
+
 /**
  * Shader is the based class for objects that return horizontal spans of colors
  * during drawing. A subclass of Shader is installed in a Paint calling
  * paint.setShader(shader). After that any object (other than a bitmap) that is
  * drawn with that paint will get its color(s) from the shader.
  */
-public class Shader {
-    
+public abstract class Shader {
+
     private final Matrix mMatrix = new Matrix();
 
     public enum TileMode {
@@ -41,7 +43,7 @@
          * mirror images so that adjacent images always seam
          */
         MIRROR  (2);
-    
+
         TileMode(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -57,7 +59,7 @@
         if (localM != null) {
             localM.set(mMatrix);
         }
-        
+
         return !mMatrix.isIdentity();
     }
 
@@ -73,4 +75,9 @@
             mMatrix.reset();
         }
     }
+
+    /**
+     * Returns a java.awt.Paint object matching this shader.
+     */
+    abstract java.awt.Paint getJavaPaint();
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient.java
index e79e970..21d8244 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import java.awt.Paint;
+
 public class SweepGradient extends Shader {
 
     /**
@@ -41,7 +43,7 @@
             throw new IllegalArgumentException(
                         "color and position arrays must be of equal length");
         }
-        
+
         // FIXME Implement shader
     }
 
@@ -56,5 +58,11 @@
     public SweepGradient(float cx, float cy, int color0, int color1) {
         // FIXME Implement shader
     }
+
+    @Override
+    Paint getJavaPaint() {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }