Merge "Add a way to insert a parent bread crumb so that deep linked settings can navigate up."
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 915c5d7..980048c 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -19,14 +19,17 @@
 import android.os.Parcelable;
 import android.os.Parcel;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
 /**
  * A simple object for retrieving / setting an interfaces configuration
  * @hide
  */
 public class InterfaceConfiguration implements Parcelable {
     public String hwAddr;
-    public int ipAddr;
-    public int netmask;
+    public InetAddress addr;
+    public InetAddress mask;
     public String interfaceFlags;
 
     public InterfaceConfiguration() {
@@ -36,21 +39,14 @@
     public String toString() {
         StringBuffer str = new StringBuffer();
 
-        str.append("ipddress "); putAddress(str, ipAddr);
-        str.append(" netmask "); putAddress(str, netmask);
+        str.append("ipddress "); str.append(addr.toString());
+        str.append(" netmask "); str.append(mask.toString());
         str.append(" flags ").append(interfaceFlags);
         str.append(" hwaddr ").append(hwAddr);
 
         return str.toString();
     }
 
-    private static void putAddress(StringBuffer buf, int addr) {
-        buf.append((addr >> 24) & 0xff).append('.').
-            append((addr >> 16) & 0xff).append('.').
-            append((addr >> 8) & 0xff).append('.').
-            append(addr & 0xff);
-    }
-
     /** Implement the Parcelable interface {@hide} */
     public int describeContents() {
         return 0;
@@ -59,8 +55,18 @@
     /** Implement the Parcelable interface {@hide} */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(hwAddr);
-        dest.writeInt(ipAddr);
-        dest.writeInt(netmask);
+        if (addr != null) {
+            dest.writeByte((byte)1);
+            dest.writeByteArray(addr.getAddress());
+        } else {
+            dest.writeByte((byte)0);
+        }
+        if (mask != null) {
+            dest.writeByte((byte)1);
+            dest.writeByteArray(mask.getAddress());
+        } else {
+            dest.writeByte((byte)0);
+        }
         dest.writeString(interfaceFlags);
     }
 
@@ -70,8 +76,16 @@
             public InterfaceConfiguration createFromParcel(Parcel in) {
                 InterfaceConfiguration info = new InterfaceConfiguration();
                 info.hwAddr = in.readString();
-                info.ipAddr = in.readInt();
-                info.netmask = in.readInt();
+                if (in.readByte() == 1) {
+                    try {
+                        info.addr = InetAddress.getByAddress(in.createByteArray());
+                    } catch (UnknownHostException e) {}
+                }
+                if (in.readByte() == 1) {
+                    try {
+                        info.mask = InetAddress.getByAddress(in.createByteArray());
+                    } catch (UnknownHostException e) {}
+                }
                 info.interfaceFlags = in.readString();
                 return info;
             }
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index e9428f7..3769cfe 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -22,6 +22,7 @@
  * Class that operates the vibrator on the device.
  * <p>
  * If your process exits, any vibration you started with will stop.
+ * </p>
  */
 public class Vibrator
 {
@@ -56,7 +57,7 @@
     /**
      * Turn the vibrator on.
      *
-     * @param milliseconds How long to vibrate for.
+     * @param milliseconds The number of milliseconds to vibrate.
      */
     public void vibrate(long milliseconds)
     {
@@ -75,12 +76,17 @@
      * Vibrate with a given pattern.
      *
      * <p>
-     * Pass in an array of ints that are the times at which to turn on or off
-     * the vibrator.  The first one is how long to wait before turning it on,
-     * and then after that it alternates.  If you want to repeat, pass the
-     * index into the pattern at which to start the repeat.
+     * Pass in an array of ints that are the durations for which to turn on or off
+     * the vibrator in milliseconds.  The first value indicates the number of milliseconds
+     * to wait before turning the vibrator on.  The next value indicates the number of milliseconds
+     * for which to keep the vibrator on before turning it off.  Subsequent values alternate
+     * between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
+     * </p><p>
+     * To cause the pattern to repeat, pass the index into the pattern array at which
+     * to start the repeat, or -1 to disable repeating.
+     * </p>
      *
-     * @param pattern an array of longs of times to turn the vibrator on or off.
+     * @param pattern an array of longs of times for which to turn the vibrator on or off.
      * @param repeat the index into pattern at which to repeat, or -1 if
      *        you don't want to repeat.
      */
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 1f19f9e..9e5abdc 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -75,6 +75,7 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -1660,20 +1661,10 @@
         try {
             ifcg = service.getInterfaceConfig(iface);
             if (ifcg != null) {
-                String[] addr = BLUETOOTH_NETMASK.split("\\.");
-                ifcg.netmask = (Integer.parseInt(addr[0]) << 24) +
-                        (Integer.parseInt(addr[1]) << 16) +
-                        (Integer.parseInt(addr[2]) << 8) +
-                        (Integer.parseInt(addr[3]));
-                if (ifcg.ipAddr == 0) {
-                    addr = address.split("\\.");
-
-                    ifcg.ipAddr = (Integer.parseInt(addr[0]) << 24) +
-                            (Integer.parseInt(addr[1]) << 16) +
-                            (Integer.parseInt(addr[2]) << 8) +
-                            (Integer.parseInt(addr[3]));
-                    ifcg.interfaceFlags =
-                        ifcg.interfaceFlags.replace("down", "up");
+                ifcg.mask = InetAddress.getByName(BLUETOOTH_NETMASK);
+                if (ifcg.addr == null) {
+                    ifcg.addr = InetAddress.getByName(address);
+                    ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
                 }
                 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
                 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 9bda637..95949b9 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -865,6 +865,9 @@
                 childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
                 childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
                 host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+                if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
+                    windowSizeMayChange = true;
+                }
             }
 
             if (DBG) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 4223040..8fb6fa3 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -192,12 +192,6 @@
 
         setSwitchTypefaceByIndex(typefaceIndex, styleIndex);
 
-        int lineHeight = appearance.getDimensionPixelSize(
-                com.android.internal.R.styleable.TextAppearance_textLineHeight, 0);
-        if (lineHeight != 0) {
-            setLineHeight(lineHeight);
-        }
-
         appearance.recycle();
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7fc7e54..c7ee57b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -766,13 +766,6 @@
                 mEditTextMultilineBackground = a.getDrawable(attr);
                 break;
 
-            case com.android.internal.R.styleable.TextView_textLineHeight:
-                int lineHeight = a.getDimensionPixelSize(attr, 0);
-                if (lineHeight != 0) {
-                    setLineHeight(lineHeight);
-                }
-                break;
-
             case com.android.internal.R.styleable.TextView_textIsSelectable:
                 mTextIsSelectable = a.getBoolean(attr, false);
                 break;
@@ -1133,15 +1126,9 @@
      * within the text can cause individual lines to be taller or shorter
      * than this height, and the layout may contain additional first-
      * or last-line padding.
-     *
-     * @attr ref android.R.styleable#TextView_textLineHeight
      */
     public int getLineHeight() {
-        if (mLineHeight != 0) {
-            return mLineHeight;
-        }
-        return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult
-                          + mSpacingAdd);
+        return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd);
     }
 
     /**
@@ -1728,26 +1715,10 @@
 
         setTypefaceByIndex(typefaceIndex, styleIndex);
         
-        int lineHeight = appearance.getDimensionPixelSize(
-                com.android.internal.R.styleable.TextAppearance_textLineHeight, 0);
-        if (lineHeight != 0) {
-            setLineHeight(lineHeight);
-        }
-
         appearance.recycle();
     }
 
     /**
-     * Set the height of a line of text in pixels. This value will override line height
-     * values stored in the font modified by lineSpacingExtra and lineSpacingMultiplier.
-     *
-     * @param lineHeight Desired height of a single line of text in pixels
-     */
-    public void setLineHeight(int lineHeight) {
-        mLineHeight = lineHeight;
-    }
-
-    /**
      * @return the size (in pixels) of the default text size in this TextView.
      */
     public float getTextSize() {
@@ -9393,7 +9364,6 @@
 
     private float                   mSpacingMult = 1;
     private float                   mSpacingAdd = 0;
-    private int                     mLineHeight = 0;
     private boolean                 mTextIsSelectable = false;
 
     private static final int        LINES = 1;
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 2cb78a5..a5fd38e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -96,6 +96,7 @@
         }
 
         mPopup.setContentWidth(Math.min(measureContentWidth(adapter), mPopupMaxWidth));
+        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
         mPopup.show();
         mPopup.getListView().setOnKeyListener(this);
     }
@@ -163,6 +164,9 @@
             final View anchor = mAnchorView != null ? mAnchorView.get() : null;
             if (anchor != null && !anchor.isShown()) {
                 dismiss();
+            } else {
+                // Recompute window size and position
+                mPopup.show();
             }
         }
     }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 181bbcc..f10e90f 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -722,9 +722,6 @@
     <!-- Color of link text (URLs). -->
     <attr name="textColorLink" format="reference|color" />
 
-    <!-- Height of a line of text. -->
-    <attr name="textLineHeight" format="dimension" />
-
     <!-- Indicates that the content of a non-editable TextView can be selected.
      Default value is false. EditText content is always selectable. -->
     <attr name="textIsSelectable" format="boolean" />
@@ -2429,8 +2426,6 @@
         <attr name="textColorHint" />
         <!-- Color of the links. -->
         <attr name="textColorLink" />
-        <!-- Height of a single line of text. -->
-        <attr name="textLineHeight" />
     </declare-styleable>
     <declare-styleable name="TextSwitcher">
     </declare-styleable>
@@ -2672,10 +2667,7 @@
         <attr name="textEditPasteWindowLayout" />
         <!-- Variation of textEditPasteWindowLayout displayed when the clipboard is empty. -->
         <attr name="textEditNoPasteWindowLayout" />
-
-        <!-- Height of a line of text. -->
-        <attr name="textLineHeight" />
-        <!-- Indicates that a non-editable text can be selected. -->
+        <!-- Indicates that the content of a non-editable text can be selected. -->
         <attr name="textIsSelectable" />
         <!--  A specific background drawable used by multi-line EditText only. -->
         <attr name="multilineBackground" format="reference"/>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index dcc88f0..3a5b238 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1358,7 +1358,6 @@
   <public type="attr" name="loopViews" />
   <public type="attr" name="dialogTheme" />
   <public type="attr" name="alertDialogTheme" />
-  <public type="attr" name="textLineHeight" />
   <public type="attr" name="dividerVertical" />
   <public type="attr" name="homeAsUpIndicator" />
   <public type="attr" name="enterFadeDuration" />
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 8dbd3e7..4290ce7 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -219,28 +219,6 @@
         }
     }
 
-    private static int stringToIpAddr(String addrString) throws UnknownHostException {
-        try {
-            String[] parts = addrString.split("\\.");
-            if (parts.length != 4) {
-                throw new UnknownHostException(addrString);
-            }
-
-            int a = Integer.parseInt(parts[0]) << 24;
-            int b = Integer.parseInt(parts[1]) << 16;
-            int c = Integer.parseInt(parts[2]) <<  8;
-            int d = Integer.parseInt(parts[3])      ;
-
-            return a | b | c | d;
-        } catch (NumberFormatException ex) {
-            throw new UnknownHostException(addrString);
-        }
-    }
-
-    public static String intToIpString(int i) {
-        return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >>  8 ) & 0xFF) + "." +
-               (i & 0xFF);
-    }
 
     //
     // INetworkManagementService members
@@ -288,18 +266,17 @@
             cfg = new InterfaceConfiguration();
             cfg.hwAddr = st.nextToken(" ");
             try {
-                cfg.ipAddr = stringToIpAddr(st.nextToken(" "));
+                cfg.addr = InetAddress.getByName(st.nextToken(" "));
             } catch (UnknownHostException uhe) {
                 Slog.e(TAG, "Failed to parse ipaddr", uhe);
-                cfg.ipAddr = 0;
             }
 
             try {
-                cfg.netmask = stringToIpAddr(st.nextToken(" "));
+                cfg.mask = InetAddress.getByName(st.nextToken(" "));
             } catch (UnknownHostException uhe) {
                 Slog.e(TAG, "Failed to parse netmask", uhe);
-                cfg.netmask = 0;
             }
+
             cfg.interfaceFlags = st.nextToken("]").trim() +"]";
         } catch (NoSuchElementException nsee) {
             throw new IllegalStateException(
@@ -312,7 +289,8 @@
     public void setInterfaceConfig(
             String iface, InterfaceConfiguration cfg) throws IllegalStateException {
         String cmd = String.format("interface setcfg %s %s %s %s", iface,
-                intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags);
+                cfg.addr.getHostAddress(), cfg.mask.getHostAddress(),
+                cfg.interfaceFlags);
         try {
             mConnector.doCommand(cmd);
         } catch (NativeDaemonConnectorException e) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 07813b0..ff703fd 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -58,6 +58,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
+import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -347,8 +348,8 @@
                         ifcg = service.getInterfaceConfig(intf);
                         if (ifcg != null) {
                             /* IP/netmask: 192.168.43.1/255.255.255.0 */
-                            ifcg.ipAddr = (192 << 24) + (168 << 16) + (43 << 8) + 1;
-                            ifcg.netmask = (255 << 24) + (255 << 16) + (255 << 8) + 0;
+                            ifcg.addr = InetAddress.getByName("192.168.43.1");
+                            ifcg.mask = InetAddress.getByName("255.255.255.0");
                             ifcg.interfaceFlags = "[up]";
 
                             service.setInterfaceConfig(intf, ifcg);
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 75a0e82..d742d4c 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -51,6 +51,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -585,16 +586,8 @@
                 try {
                     ifcg = service.getInterfaceConfig(iface);
                     if (ifcg != null) {
-                        String[] addr = USB_NEAR_IFACE_ADDR.split("\\.");
-                        ifcg.ipAddr = (Integer.parseInt(addr[0]) << 24) +
-                                (Integer.parseInt(addr[1]) << 16) +
-                                (Integer.parseInt(addr[2]) << 8) +
-                                (Integer.parseInt(addr[3]));
-                        addr = USB_NETMASK.split("\\.");
-                        ifcg.netmask = (Integer.parseInt(addr[0]) << 24) +
-                                (Integer.parseInt(addr[1]) << 16) +
-                                (Integer.parseInt(addr[2]) << 8) +
-                                (Integer.parseInt(addr[3]));
+                        ifcg.addr = InetAddress.getByName(USB_NEAR_IFACE_ADDR);
+                        ifcg.mask = InetAddress.getByName(USB_NETMASK);
                         if (enabled) {
                             ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
                         } else {
diff --git a/tests/HwAccelerationTest/.classpath b/tests/HwAccelerationTest/.classpath
new file mode 100644
index 0000000..609aa00
--- /dev/null
+++ b/tests/HwAccelerationTest/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tests/HwAccelerationTest/.gitignore b/tests/HwAccelerationTest/.gitignore
new file mode 100644
index 0000000..f178f17
--- /dev/null
+++ b/tests/HwAccelerationTest/.gitignore
@@ -0,0 +1,3 @@
+bin
+gen
+local.properties
\ No newline at end of file
diff --git a/tests/HwAccelerationTest/.project b/tests/HwAccelerationTest/.project
new file mode 100644
index 0000000..7c04d3c
--- /dev/null
+++ b/tests/HwAccelerationTest/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>HwAccelerationTest</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 7fa71a9..c60613c 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -17,7 +17,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.test.hwui">
 
-    <uses-permission android:name="android.permission.INTERNET" />    
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-sdk android:minSdkVersion="Froyo" />
     
     <application
         android:label="HwUi"
diff --git a/tests/HwAccelerationTest/default.properties b/tests/HwAccelerationTest/default.properties
new file mode 100644
index 0000000..5a8ea50
--- /dev/null
+++ b/tests/HwAccelerationTest/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-Froyo
diff --git a/tests/HwAccelerationTest/res/layout/advanced_blend.xml b/tests/HwAccelerationTest/res/layout/advanced_blend.xml
new file mode 100644
index 0000000..6efdd73
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/advanced_blend.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.android.test.hwui.AdvancedBlendActivity.ShadersView
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="fill_parent"
+  android:layout_height="fill_parent">
+</com.android.test.hwui.AdvancedBlendActivity.ShadersView>
diff --git a/tests/HwAccelerationTest/res/layout/advanced_gradient.xml b/tests/HwAccelerationTest/res/layout/advanced_gradient.xml
new file mode 100644
index 0000000..dd937f9
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/advanced_gradient.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.android.test.hwui.AdvancedGradientsActivity.GradientsView
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="fill_parent"
+  android:layout_height="fill_parent">
+</com.android.test.hwui.AdvancedGradientsActivity.GradientsView>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java
index 5baa20c..a83005b 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java
@@ -41,7 +41,7 @@
         setContentView(new ShadersView(this));
     }
 
-    static class ShadersView extends View {
+    public static class ShadersView extends View {
         private BitmapShader mScaledShader;
         private int mTexWidth;
         private int mTexHeight;
@@ -57,7 +57,7 @@
         private ComposeShader mCompose6Shader;
         private BitmapShader mScaled2Shader;
 
-        ShadersView(Context c) {
+        public ShadersView(Context c) {
             super(c);
 
             Bitmap texture = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
@@ -71,7 +71,7 @@
             Matrix m2 = new Matrix();
             m2.setScale(0.5f, 0.5f);
             mScaledShader.setLocalMatrix(m2);
-            
+
             mScaled2Shader = new BitmapShader(texture, Shader.TileMode.MIRROR,
                     Shader.TileMode.MIRROR);
             Matrix m3 = new Matrix();
@@ -80,7 +80,7 @@
 
             mHorGradient = new LinearGradient(0.0f, 0.0f, mDrawWidth, 0.0f,
                     Color.BLACK, Color.WHITE, Shader.TileMode.CLAMP);
-            
+
             mComposeShader = new ComposeShader(mScaledShader, mHorGradient,
                     PorterDuff.Mode.DARKEN);
             mCompose2Shader = new ComposeShader(mScaledShader, mHorGradient,
@@ -107,7 +107,7 @@
 
             mPaint.setShader(mComposeShader);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
-            
+
             canvas.translate(0.0f, 40.0f + mDrawHeight);
             mPaint.setShader(mCompose2Shader);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
@@ -117,10 +117,10 @@
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
 
             canvas.restore();
-            
+
             canvas.save();
             canvas.translate(40.0f + mDrawWidth + 40.0f, 40.0f);
-            
+
             mPaint.setShader(mCompose4Shader);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
 
@@ -131,7 +131,7 @@
             canvas.translate(0.0f, 40.0f + mDrawHeight);
             mPaint.setShader(mCompose6Shader);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
-            
+
             canvas.restore();
         }
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
index 27974e7..b0b54eb 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
@@ -36,7 +36,7 @@
         setContentView(new GradientsView(this));
     }
 
-    static class GradientsView extends View {
+    public static class GradientsView extends View {
         private final Paint mPaint;
         private final SweepGradient mSweepGradient;
         private final RadialGradient mRadialGradient;
@@ -44,7 +44,7 @@
         private final Matrix mMatrix2;
         private final Matrix mMatrix3;
 
-        GradientsView(Context c) {
+        public GradientsView(Context c) {
             super(c);
 
             mSweepGradient = new SweepGradient(0.0f, 0.0f, 0xff000000, 0xffffffff);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java
index 8fa626b..f8422f4 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java
@@ -51,15 +51,12 @@
         final SeekBar rotateView = new SeekBar(this);
         rotateView.setMax(360);
         rotateView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-            @Override
             public void onStopTrackingTouch(SeekBar seekBar) {
             }
 
-            @Override
             public void onStartTrackingTouch(SeekBar seekBar) {
             }
 
-            @Override
             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                 gradientView.setRotationY((float) progress);
                 radialGradientView.setRotationX((float) progress);
@@ -67,7 +64,7 @@
                 bitmapView.setRotationX((float) progress);
             }
         });
-        
+
         layout.addView(shadersView);
         layout.addView(gradientView, new FrameLayout.LayoutParams(
                 200, 200, Gravity.CENTER));
@@ -90,7 +87,7 @@
 
         setContentView(layout);
     }
-    
+
     static class BitmapView extends View {
         private final Paint mPaint;
 
@@ -116,7 +113,7 @@
             canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
         }
     }
-    
+
     static class GradientView extends View {
         private final Paint mPaint;
 
@@ -166,14 +163,14 @@
             canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
         }
     }
-    
+
     static class SweepGradientView extends View {
         private final Paint mPaint;
 
         SweepGradientView(Context c) {
             super(c);
 
-            SweepGradient gradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff);                
+            SweepGradient gradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff);
             mPaint = new Paint();
             mPaint.setShader(gradient);
         }
@@ -190,7 +187,7 @@
             canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mPaint);
         }
     }
-        
+
     static class ShadersView extends View {
         private final Paint mPaint;
         private final float mDrawWidth;
@@ -232,12 +229,12 @@
 
             top += 40.0f + mDrawHeight;
             bottom += 40.0f + mDrawHeight;
-            
+
             mMatrix.setScale(1, mDrawHeight);
             mMatrix.postTranslate(left, top);
             mGradient.setLocalMatrix(mMatrix);
             canvas.drawRect(left, top, right, top + mDrawHeight, mPaint);
-            
+
             left += 40.0f + mDrawWidth;
             right += 40.0f + mDrawWidth;
             top -= 40.0f + mDrawHeight;
@@ -251,13 +248,13 @@
 
             top += 40.0f + mDrawHeight;
             bottom += 40.0f + mDrawHeight;
-            
+
             mMatrix.setScale(1, mDrawWidth);
             mMatrix.postRotate(-90);
             mMatrix.postTranslate(left, top);
             mGradient.setLocalMatrix(mMatrix);
             canvas.drawRect(left, top, left + mDrawWidth, bottom, mPaint);
-           
+
             canvas.restore();
         }
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java
index 773d390..f40b89d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java
@@ -43,9 +43,8 @@
         ));
 
         setContentView(layout);
-        
+
         layout.post(new Runnable() {
-            @Override
             public void run() {
                 Bitmap b = Bitmap.createBitmap(gamma.getWidth(), gamma.getHeight(),
                         Bitmap.Config.ARGB_8888);
@@ -88,7 +87,7 @@
 
             final LinearLayout layout = new LinearLayout(this);
             layout.setOrientation(LinearLayout.VERTICAL);
-        
+
             final GammaTextView gamma = new GammaTextView(this);
             final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                     LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT
diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
index 042d557..bc4ccd2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
@@ -119,20 +119,23 @@
                             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);
+                            // remove the integer part to stay in the [0,1] range.
+                            // we also need to invert the value from [-1,0] to [0, 1]
+                            pos = pos - (float)Math.floor(pos);
                             break;
                         case MIRROR:
+                            // this is the same as the positive side, just make the value positive
+                            // first.
+                            pos = Math.abs(pos);
+
                             // 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);
+                            int intPart = (int)Math.floor(pos);
                             pos = pos - intPart;
-                            // 0  -> -1 : mirrored order
-                            // -1 -> -2: normal order
+                            // 0 -> 1 : normal order
+                            // 1 -> 2: mirrored
                             // etc..
-                            // this means if the intpart is even we invert
-                            if ((intPart % 2) == 0) {
+                            // this means if the intpart is odd we invert
+                            if ((intPart % 2) == 1) {
                                 pos = 1.f - pos;
                             }
                             break;
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 7573dc1..862b4544 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -16,11 +16,14 @@
 
 package android.graphics;
 
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Shader.TileMode;
 
 import java.awt.Paint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
 
 /**
  * Delegate implementing the native methods of android.graphics.LinearGradient
@@ -115,7 +118,7 @@
      * {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile
      * modes.
      */
-    private static class LinearGradientPaint extends GradientPaint {
+    private class LinearGradientPaint extends GradientPaint {
 
         private final float mX0;
         private final float mY0;
@@ -126,11 +129,11 @@
         public LinearGradientPaint(float x0, float y0, float x1, float y1, int colors[],
                 float positions[], TileMode tile) {
             super(colors, positions, tile);
-                mX0 = x0;
-                mY0 = y0;
-                mDx = x1 - x0;
-                mDy = y1 - y0;
-                mDSize2 = mDx * mDx + mDy * mDy;
+            mX0 = x0;
+            mY0 = y0;
+            mDx = x1 - x0;
+            mDy = y1 - y0;
+            mDSize2 = mDx * mDx + mDy * mDy;
         }
 
         public java.awt.PaintContext createContext(
@@ -140,16 +143,37 @@
                 java.awt.geom.AffineTransform  xform,
                 java.awt.RenderingHints        hints) {
             precomputeGradientColors();
-            return new LinearGradientPaintContext(colorModel);
+
+            AffineTransform canvasMatrix;
+            try {
+                canvasMatrix = xform.createInverse();
+            } catch (NoninvertibleTransformException e) {
+                Bridge.getLog().error(null, "Unable to inverse matrix in LinearGradient", e);
+                canvasMatrix = new AffineTransform();
+            }
+
+            AffineTransform localMatrix = getLocalMatrix();
+            try {
+                localMatrix = localMatrix.createInverse();
+            } catch (NoninvertibleTransformException e) {
+                Bridge.getLog().error(null, "Unable to inverse matrix in LinearGradient", e);
+                localMatrix = new AffineTransform();
+            }
+
+            return new LinearGradientPaintContext(canvasMatrix, localMatrix, colorModel);
         }
 
         private class LinearGradientPaintContext implements java.awt.PaintContext {
 
+            private final AffineTransform mCanvasMatrix;
+            private final AffineTransform mLocalMatrix;
             private final java.awt.image.ColorModel mColorModel;
 
-            public LinearGradientPaintContext(java.awt.image.ColorModel colorModel) {
+            public LinearGradientPaintContext(AffineTransform canvasMatrix,
+                    AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+                mCanvasMatrix = canvasMatrix;
+                mLocalMatrix = localMatrix;
                 mColorModel = colorModel;
-                // FIXME: so far all this is always the same rect gotten in getRaster with an identity matrix?
             }
 
             public void dispose() {
@@ -165,31 +189,22 @@
 
                 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];
+                int index = 0;
+                float[] pt1 = new float[2];
+                float[] pt2 = new float[2];
+                for (int iy = 0 ; iy < h ; iy++) {
                     for (int ix = 0 ; ix < w ; ix++) {
-                        line[ix] = getColor(ix + x, mX0, mDx);
-                    }
+                        // handle the canvas transform
+                        pt1[0] = x + ix;
+                        pt1[1] = y + iy;
+                        mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
 
-                    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);
-                        }
+                        // handle the local matrix.
+                        pt1[0] = pt2[0];
+                        pt1[1] = pt2[1];
+                        mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        data[index++] = getColor(pt2[0], pt2[1]);
                     }
                 }
 
@@ -199,13 +214,6 @@
             }
         }
 
-        /** Returns a color for the easy vertical/horizontal mode */
-        private int getColor(float absPos, float refPos, float refSize) {
-            float pos = (absPos - refPos) / refSize;
-
-            return getGradientColor(pos);
-        }
-
         /**
          * Returns a color for an arbitrary point.
          */
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index bef8c8c..6b43544 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -471,7 +471,7 @@
             return false;
         }
 
-        d.preTransform(getRotate(degrees, px, py));
+        d.postTransform(getRotate(degrees, px, py));
         return true;
     }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index c36ce53..eebf378 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -16,11 +16,14 @@
 
 package android.graphics;
 
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Shader.TileMode;
 
 import java.awt.Paint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
 
 /**
  * Delegate implementing the native methods of android.graphics.RadialGradient
@@ -105,18 +108,17 @@
     private RadialGradient_Delegate(float x, float y, float radius, int colors[], float positions[],
             TileMode tile) {
         super(colors, positions);
-
         mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile);
     }
 
-    private static class RadialGradientPaint extends GradientPaint {
+    private class RadialGradientPaint extends GradientPaint {
 
         private final float mX;
         private final float mY;
         private final float mRadius;
 
-        public RadialGradientPaint(float x, float y, float radius, int[] colors, float[] positions,
-                TileMode mode) {
+        public RadialGradientPaint(float x, float y, float radius,
+                int[] colors, float[] positions, TileMode mode) {
             super(colors, positions, mode);
             mX = x;
             mY = y;
@@ -130,14 +132,36 @@
                 java.awt.geom.AffineTransform xform,
                 java.awt.RenderingHints       hints) {
             precomputeGradientColors();
-            return new RadialGradientPaintContext(colorModel);
+
+            AffineTransform canvasMatrix;
+            try {
+                canvasMatrix = xform.createInverse();
+            } catch (NoninvertibleTransformException e) {
+                Bridge.getLog().error(null, "Unable to inverse matrix in RadialGradient", e);
+                canvasMatrix = new AffineTransform();
+            }
+
+            AffineTransform localMatrix = getLocalMatrix();
+            try {
+                localMatrix = localMatrix.createInverse();
+            } catch (NoninvertibleTransformException e) {
+                Bridge.getLog().error(null, "Unable to inverse matrix in RadialGradient", e);
+                localMatrix = new AffineTransform();
+            }
+
+            return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel);
         }
 
         private class RadialGradientPaintContext implements java.awt.PaintContext {
 
+            private final AffineTransform mCanvasMatrix;
+            private final AffineTransform mLocalMatrix;
             private final java.awt.image.ColorModel mColorModel;
 
-            public RadialGradientPaintContext(java.awt.image.ColorModel colorModel) {
+            public RadialGradientPaintContext(AffineTransform canvasMatrix,
+                    AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+                mCanvasMatrix = canvasMatrix;
+                mLocalMatrix = localMatrix;
                 mColorModel = colorModel;
             }
 
@@ -157,10 +181,22 @@
                 // compute distance from each point to the center, and figure out the distance from
                 // it.
                 int index = 0;
+                float[] pt1 = new float[2];
+                float[] pt2 = new float[2];
                 for (int iy = 0 ; iy < h ; iy++) {
                     for (int ix = 0 ; ix < w ; ix++) {
-                        float _x = x + ix - mX;
-                        float _y = y + iy - mY;
+                        // handle the canvas transform
+                        pt1[0] = x + ix;
+                        pt1[1] = y + iy;
+                        mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        // handle the local matrix
+                        pt1[0] = pt2[0] - mX;
+                        pt1[1] = pt2[1] - mY;
+                        mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        float _x = pt2[0];
+                        float _y = pt2[1];
                         float distance = (float) Math.sqrt(_x * _x + _y * _y);
 
                         data[index++] = getGradientColor(distance / mRadius);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 646ac80..7bf1443 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -18,6 +18,8 @@
 
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
+import java.awt.geom.AffineTransform;
+
 /**
  * Delegate implementing the native methods of android.graphics.Shader
  *
@@ -109,4 +111,19 @@
 
     // ---- Private delegate/helper methods ----
 
+    protected AffineTransform getLocalMatrix() {
+        Matrix_Delegate localMatrixDelegate = null;
+        if (mLocalMatrix > 0) {
+            localMatrixDelegate = Matrix_Delegate.getDelegate(mLocalMatrix);
+            if (localMatrixDelegate == null) {
+                assert false;
+                return new AffineTransform();
+            }
+
+            return localMatrixDelegate.getAffineTransform();
+        }
+
+        return new AffineTransform();
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 358c3c7..97c3cfd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -16,9 +16,12 @@
 
 package android.graphics;
 
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import java.awt.Paint;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
 
 /**
  * Delegate implementing the native methods of android.graphics.SweepGradient
@@ -90,16 +93,16 @@
     private SweepGradient_Delegate(float cx, float cy,
                          int colors[], float positions[]) {
         super(colors, positions);
-
         mJavaPaint = new SweepGradientPaint(cx, cy, mColors, mPositions);
     }
 
-    private static class SweepGradientPaint extends GradientPaint {
+    private class SweepGradientPaint extends GradientPaint {
 
         private final float mCx;
         private final float mCy;
 
-        public SweepGradientPaint(float cx, float cy, int[] colors, float[] positions) {
+        public SweepGradientPaint(float cx, float cy, int[] colors,
+                float[] positions) {
             super(colors, positions, null /*tileMode*/);
             mCx = cx;
             mCy = cy;
@@ -112,14 +115,36 @@
                 java.awt.geom.AffineTransform xform,
                 java.awt.RenderingHints       hints) {
             precomputeGradientColors();
-            return new SweepGradientPaintContext(colorModel);
+
+            AffineTransform canvasMatrix;
+            try {
+                canvasMatrix = xform.createInverse();
+            } catch (NoninvertibleTransformException e) {
+                Bridge.getLog().error(null, "Unable to inverse matrix in SweepGradient", e);
+                canvasMatrix = new AffineTransform();
+            }
+
+            AffineTransform localMatrix = getLocalMatrix();
+            try {
+                localMatrix = localMatrix.createInverse();
+            } catch (NoninvertibleTransformException e) {
+                Bridge.getLog().error(null, "Unable to inverse matrix in SweepGradient", e);
+                localMatrix = new AffineTransform();
+            }
+
+            return new SweepGradientPaintContext(canvasMatrix, localMatrix, colorModel);
         }
 
         private class SweepGradientPaintContext implements java.awt.PaintContext {
 
+            private final AffineTransform mCanvasMatrix;
+            private final AffineTransform mLocalMatrix;
             private final java.awt.image.ColorModel mColorModel;
 
-            public SweepGradientPaintContext(java.awt.image.ColorModel colorModel) {
+            public SweepGradientPaintContext(AffineTransform canvasMatrix,
+                    AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+                mCanvasMatrix = canvasMatrix;
+                mLocalMatrix = localMatrix;
                 mColorModel = colorModel;
             }
 
@@ -139,10 +164,23 @@
                 // compute angle from each point to the center, and figure out the distance from
                 // it.
                 int index = 0;
+                float[] pt1 = new float[2];
+                float[] pt2 = new float[2];
                 for (int iy = 0 ; iy < h ; iy++) {
                     for (int ix = 0 ; ix < w ; ix++) {
-                        float dx = x + ix - mCx;
-                        float dy = y + iy - mCy;
+                        // handle the canvas transform
+                        pt1[0] = x + ix;
+                        pt1[1] = y + iy;
+                        mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        // handle the local matrix
+                        pt1[0] = pt2[0] - mCx;
+                        pt1[1] = pt2[1] - mCy;
+                        mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        float dx = pt2[0];
+                        float dy = pt2[1];
+
                         float angle;
                         if (dx == 0) {
                             angle = (float) (dy < 0 ? 3 * Math.PI / 2 : Math.PI / 2);