Merge "Rename action to ACTION_INPUT_METHOD_SUBTYPE_SETTINGS" into honeycomb
diff --git a/Android.mk b/Android.mk
index 5d989d1..7728b02 100644
--- a/Android.mk
+++ b/Android.mk
@@ -384,10 +384,10 @@
 		-hdf android.hasSamples 1 \
 		-samplecode $(sample_dir)/AccessibilityService \
 		            resources/samples/AccessibilityService "Accessibility Service" \
-		-samplecode $(sample_dir)/ApiDemos \
-		            resources/samples/ApiDemos "API Demos" \
 		-samplecode $(sample_dir)/AccelerometerPlay \
 		            resources/samples/AccelerometerPlay "Accelerometer Play" \
+	  -samplecode $(sample_dir)/ApiDemos \
+		            resources/samples/ApiDemos "API Demos" \
 		-samplecode $(sample_dir)/BackupRestore \
 		            resources/samples/BackupRestore "Backup and Restore" \
 		-samplecode $(sample_dir)/BluetoothChat \
@@ -396,16 +396,20 @@
 		            resources/samples/BusinessCard "Business Card" \
 		-samplecode $(sample_dir)/ContactManager \
 		            resources/samples/ContactManager "Contact Manager" \
-                -samplecode $(sample_dir)/CubeLiveWallpaper \
-                            resources/samples/CubeLiveWallpaper "Live Wallpaper" \
+    -samplecode $(sample_dir)/CubeLiveWallpaper \
+                resources/samples/CubeLiveWallpaper "Cube Live Wallpaper" \
 		-samplecode $(sample_dir)/Home \
 		            resources/samples/Home "Home" \
+                -samplecode $(sample_dir)/Honeycomb-Gallery \
+                            resources/samples/Honeycomb-Gallery "Honeycomb Gallery" \
 		-samplecode $(sample_dir)/JetBoy \
 		            resources/samples/JetBoy "JetBoy" \
 		-samplecode $(sample_dir)/LunarLander \
 		            resources/samples/LunarLander "Lunar Lander" \
 		-samplecode $(sample_dir)/MultiResolution \
 		            resources/samples/MultiResolution "Multiple Resolutions" \
+		-samplecode $(sample_dir)/NFCDemo \
+		            resources/samples/NFCDemo "NFC Demo" \
 		-samplecode $(sample_dir)/NotePad \
 		            resources/samples/NotePad "Note Pad" \
 		-samplecode $(sample_dir)/SampleSyncAdapter \
diff --git a/api/11.xml b/api/11.xml
index 4653ab5..d668883 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -240630,6 +240630,17 @@
  visibility="public"
 >
 </method>
+<method name="fyiWillBeAdvancedByHostKThx"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAdapter"
  return="android.widget.Adapter"
  abstract="false"
@@ -240885,17 +240896,6 @@
  visibility="public"
 >
 </method>
-<method name="willBeAdvancedByHost"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 </class>
 <class name="AdapterViewFlipper"
  extends="android.widget.AdapterViewAnimator"
diff --git a/api/current.xml b/api/current.xml
index 4e8acb6..a63a867 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -39712,6 +39712,16 @@
  visibility="public"
 >
 </field>
+<field name="previewImage"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="provider"
  type="android.content.ComponentName"
  transient="false"
@@ -240641,6 +240651,17 @@
  visibility="public"
 >
 </method>
+<method name="fyiWillBeAdvancedByHostKThx"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAdapter"
  return="android.widget.Adapter"
  abstract="false"
@@ -240896,17 +240917,6 @@
  visibility="public"
 >
 </method>
-<method name="willBeAdvancedByHost"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 </class>
 <class name="AdapterViewFlipper"
  extends="android.widget.AdapterViewAnimator"
@@ -260337,7 +260347,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/animation/package.html b/core/java/android/animation/package.html
index b66669b..ff43260 100644
--- a/core/java/android/animation/package.html
+++ b/core/java/android/animation/package.html
@@ -1,6 +1,21 @@
 <html>
 <body>
-Provides classes for animating values over time, and setting those values on target
-objects.
+<p>
+These classes provide functionality for the property animation system, which allows you 
+to animate object properties of any type. <code>int</code>, <code>float</code>, and hexadecimal
+color values are supported by default. You can animate any other type by telling the system how
+to calculate the values for that given type with a custom {@link android.animation.TypeEvaluator}.
+</p>
+
+<p>
+You can set many different types of interpolators (contained in {@link android.view.animation}),
+specify {@link android.animation.Keyframe keyframes}, or group animations to play sequentially
+or simultaneously (with {@link android.animation.AnimatorSet}) to further control your animation
+behaviors.</p>
+
+<p>
+For a guide on how to use the property animation system, see the
+<a href="{@docRoot}guide/topics/media/index.html">Animation</a> developer guide.
+</p>
 </body>
 </html>
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index a3db01d..fe33782 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -121,8 +121,6 @@
      *
      * <p>This field corresponds to the <code>android:previewImage</code> attribute in
      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
-     * 
-     * @hide Pending API approval
      */
 	public int previewImage;
 
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index f480554..d82f051 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -635,9 +635,13 @@
 
     @Override
     public void drawCircle(float cx, float cy, float radius, Paint paint) {
-        throw new UnsupportedOperationException();
+        boolean hasModifier = setupModifiers(paint);
+        nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
+        if (hasModifier) nResetModifiers(mRenderer);        
     }
 
+    private native void nDrawCircle(int renderer, float cx, float cy, float radius, int paint);
+
     @Override
     public void drawColor(int color) {
         drawColor(color, PorterDuff.Mode.SRC_OVER);
@@ -773,9 +777,15 @@
 
     @Override
     public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
-        // TODO: Implement
+        boolean hasModifier = setupModifiers(paint);
+        nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
+                rx, ry, paint.mNativePaint);
+        if (hasModifier) nResetModifiers(mRenderer);        
     }
 
+    private native void nDrawRoundRect(int renderer, float left, float top,
+            float right, float bottom, float rx, float y, int paint);
+
     @Override
     public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
         if ((index | count | (index + count) | (text.length - index - count)) < 0) {
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index c27082f..4c1279ff 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -981,11 +981,21 @@
         // items from the Adapter.
     }
 
+    /**
+     * Called by an {@link android.appwidget.AppWidgetHost} in order to advance the current view when
+     * it is being used within an app widget.
+     */
     public void advance() {
         showNext();
     }
 
-    public void willBeAdvancedByHost() {
+    /**
+     * Called by an {@link android.appwidget.AppWidgetHost} to indicate that it will be
+     * automatically advancing the views of this {@link AdapterViewAnimator} by calling
+     * {@link AdapterViewAnimator#advance()} at some point in the future. This allows subclasses to
+     * perform any required setup, for example, to stop automatically advancing their children.
+     */
+    public void fyiWillBeAdvancedByHostKThx() {
     }
 
     @Override
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index 7721688..273c258 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -258,8 +258,14 @@
         }
     };
 
+    /**
+     * Called by an {@link android.appwidget.AppWidgetHost} to indicate that it will be
+     * automatically advancing the views of this {@link AdapterViewFlipper} by calling
+     * {@link AdapterViewFlipper#advance()} at some point in the future. This allows
+     * {@link AdapterViewFlipper} to prepare by no longer Advancing its children.
+     */
     @Override
-    public void willBeAdvancedByHost() {
+    public void fyiWillBeAdvancedByHostKThx() {
         mAdvancedByHost = true;
         updateRunning(false);
     }
diff --git a/core/java/android/widget/Advanceable.java b/core/java/android/widget/Advanceable.java
index bb162de..dc13ebb7 100644
--- a/core/java/android/widget/Advanceable.java
+++ b/core/java/android/widget/Advanceable.java
@@ -34,5 +34,5 @@
      * Called by the AppWidgetHost once before it begins to call advance(), allowing the
      * collection to do any required setup.
      */
-    public void willBeAdvancedByHost();
+    public void fyiWillBeAdvancedByHostKThx();
 }
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 79d6a81..439e0ca 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -28,7 +28,6 @@
 import android.os.Build;
 import android.os.IBinder;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -1087,7 +1086,14 @@
                 p.width = Math.min(p.width, displayFrameWidth);
             }
 
-            p.y = Math.max(p.y, displayFrame.top);
+            if (onTop) {
+                int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
+                if (popupTop < 0) {
+                    p.y += popupTop;
+                }
+            } else {
+                p.y = Math.max(p.y, displayFrame.top);
+            }
         }
 
         p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java
index 16126aa..e5a3de2 100644
--- a/core/java/android/widget/RemoteViewsService.java
+++ b/core/java/android/widget/RemoteViewsService.java
@@ -42,7 +42,7 @@
     /**
      * An interface for an adapter between a remote collection view (ListView, GridView, etc) and
      * the underlying data for that view.  The implementor is responsible for making a RemoteView
-     * for each item in the data set.
+     * for each item in the data set. This interface is a thin wrapper around {@link Adapter}.
      * 
      * @see android.widget.Adapter
      * @see android.appwidget.AppWidgetManager
@@ -53,24 +53,72 @@
          * multiple RemoteViewAdapters depending on the intent passed.
          */
         public void onCreate();
+
         /**
          * Called when notifyDataSetChanged() is triggered on the remote adapter. This allows a
          * RemoteViewsFactory to respond to data changes by updating any internal references.
          *
+         * Note: expensive tasks can be safely performed synchronously within this method. In the
+         * interim, the old data will be displayed within the widget.
+         *
          * @see android.appwidget.AppWidgetManager#notifyAppWidgetViewDataChanged(int[], int)
          */
         public void onDataSetChanged();
+
         /**
          * Called when the last RemoteViewsAdapter that is associated with this factory is
          * unbound.
          */
         public void onDestroy();
 
+        /**
+         * See {@link Adapter#getCount()}
+         *
+         * @return Count of items.
+         */
         public int getCount();
+
+        /**
+         * See {@link Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
+         *
+         * Note: expensive tasks can be safely performed synchronously within this method, and a
+         * loading view will be displayed in the interim. See {@link #getLoadingView()}.
+         *
+         * @param position The position of the item within the Factory's data set of the item whose
+         *        view we want.
+         * @return A RemoteViews object corresponding to the data at the specified position.
+         */
         public RemoteViews getViewAt(int position);
+
+        /**
+         * This allows for the use of a custom loading view which appears between the time that
+         * {@link #getViewAt(int)} is called and returns. If null is returned, a default loading
+         * view will be used.
+         *
+         * @return The RemoteViews representing the desired loading view.
+         */
         public RemoteViews getLoadingView();
+
+        /**
+         * See {@link Adapter#getViewTypeCount()}.
+         *
+         * @return The number of types of Views that will be returned by this factory.
+         */
         public int getViewTypeCount();
+
+        /**
+         * See {@link Adapter#getItemId(int)}.
+         *
+         * @param position The position of the item within the data set whose row id we want.
+         * @return The id of the item at the specified position.
+         */
         public long getItemId(int position);
+
+        /**
+         * See {@link Adapter#hasStableIds()}.
+         *
+         * @return True if the same id always refers to the same object.
+         */
         public boolean hasStableIds();
     }
 
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index e38a69f..0baddcb 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -23,14 +23,13 @@
 import android.content.DialogInterface.OnClickListener;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 
 
 /**
@@ -70,8 +69,6 @@
 
     private int mGravity;
 
-    private LayoutObserver mLayoutObserver;
-
     /**
      * Construct a new spinner with the given context's theme.
      *
@@ -172,7 +169,6 @@
                     com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0));
 
             mPopup = popup;
-            mLayoutObserver = new LayoutObserver();
             break;
         }
         }
@@ -425,11 +421,6 @@
             handled = true;
 
             if (!mPopup.isShowing()) {
-                if (mLayoutObserver != null) {
-                    final ViewTreeObserver vto = getViewTreeObserver();
-                    vto.addOnGlobalLayoutListener(mLayoutObserver);
-                    vto.addOnScrollChangedListener(mLayoutObserver);
-                }
                 mPopup.show();
             }
         }
@@ -677,7 +668,6 @@
             super.show();
             getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
             setSelection(Spinner.this.getSelectedItemPosition());
-            setOnDismissListener(mLayoutObserver);
         }
 
         @Override
@@ -728,28 +718,4 @@
                     ViewGroup.LayoutParams.WRAP_CONTENT);
         }
     }
-
-    private class LayoutObserver implements ViewTreeObserver.OnGlobalLayoutListener,
-            ViewTreeObserver.OnScrollChangedListener, PopupWindow.OnDismissListener {
-        @Override
-        public void onScrollChanged() {
-            if (mPopup != null && mPopup.isShowing()) {
-                mPopup.show();
-            }
-        }
-
-        @Override
-        public void onGlobalLayout() {
-            if (mPopup != null && mPopup.isShowing()) {
-                mPopup.show();
-            }
-        }
-
-        @Override
-        public void onDismiss() {
-            ViewTreeObserver vto = getViewTreeObserver();
-            vto.removeGlobalOnLayoutListener(mLayoutObserver);
-            vto.removeOnScrollChangedListener(mLayoutObserver);
-        }
-    }
 }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 2c10077..22edf6d 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -347,6 +347,9 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     @android.view.RemotableViewMethod
     public void showNext() {
@@ -362,6 +365,9 @@
         super.showNext();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     @android.view.RemotableViewMethod
     public void showPrevious() {
@@ -474,6 +480,9 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
@@ -561,6 +570,9 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         super.onTouchEvent(ev);
@@ -939,6 +951,9 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void onRemoteAdapterConnected() {
         super.onRemoteAdapterConnected();
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index ac491ea..bfd2b58e 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -299,6 +299,17 @@
     renderer->drawRect(left, top, right, bottom, paint);
 }
 
+static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
+        jfloat rx, jfloat ry, SkPaint* paint) {
+    renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
+}
+
+static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer, jfloat x, jfloat y, jfloat radius, SkPaint* paint) {
+    renderer->drawCircle(x, y, radius, paint);
+}
+
 static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject canvas,
         OpenGLRenderer* renderer, SkRegion* region, SkPaint* paint) {
     SkRegion::Iterator it(*region);
@@ -570,6 +581,8 @@
     { "nDrawColor",         "(III)V",          (void*) android_view_GLES20Canvas_drawColor },
     { "nDrawRect",          "(IFFFFI)V",       (void*) android_view_GLES20Canvas_drawRect },
     { "nDrawRects",         "(III)V",          (void*) android_view_GLES20Canvas_drawRects },
+    { "nDrawRoundRect",     "(IFFFFFFI)V",     (void*) android_view_GLES20Canvas_drawRoundRect },
+    { "nDrawCircle",        "(IFFFI)V",        (void*) android_view_GLES20Canvas_drawCircle },
     { "nDrawPath",          "(III)V",          (void*) android_view_GLES20Canvas_drawPath },
     { "nDrawLines",         "(I[FIII)V",       (void*) android_view_GLES20Canvas_drawLines },
 
diff --git a/packages/VpnServices/res/drawable/vpn_connected.png b/core/res/res/drawable-hdpi/vpn_connected.png
similarity index 100%
rename from packages/VpnServices/res/drawable/vpn_connected.png
rename to core/res/res/drawable-hdpi/vpn_connected.png
Binary files differ
diff --git a/packages/VpnServices/res/drawable/vpn_disconnected.png b/core/res/res/drawable-hdpi/vpn_disconnected.png
similarity index 100%
rename from packages/VpnServices/res/drawable/vpn_disconnected.png
rename to core/res/res/drawable-hdpi/vpn_disconnected.png
Binary files differ
diff --git a/packages/VpnServices/res/drawable/vpn_connected.png b/core/res/res/drawable-ldpi/vpn_connected.png
similarity index 100%
copy from packages/VpnServices/res/drawable/vpn_connected.png
copy to core/res/res/drawable-ldpi/vpn_connected.png
Binary files differ
diff --git a/packages/VpnServices/res/drawable/vpn_disconnected.png b/core/res/res/drawable-ldpi/vpn_disconnected.png
similarity index 100%
copy from packages/VpnServices/res/drawable/vpn_disconnected.png
copy to core/res/res/drawable-ldpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png
new file mode 100644
index 0000000..137923b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png
new file mode 100644
index 0000000..62b1deb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..ab30a77
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png
new file mode 100644
index 0000000..9274bc7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png
new file mode 100644
index 0000000..e46155e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/packages/VpnServices/res/drawable/vpn_connected.png b/core/res/res/drawable-mdpi/vpn_connected.png
similarity index 100%
copy from packages/VpnServices/res/drawable/vpn_connected.png
copy to core/res/res/drawable-mdpi/vpn_connected.png
Binary files differ
diff --git a/packages/VpnServices/res/drawable/vpn_disconnected.png b/core/res/res/drawable-mdpi/vpn_disconnected.png
similarity index 100%
copy from packages/VpnServices/res/drawable/vpn_disconnected.png
copy to core/res/res/drawable-mdpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal.9.png b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal.9.png
new file mode 100644
index 0000000..0fbdbfa
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png
new file mode 100644
index 0000000..ae97453
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png
new file mode 100644
index 0000000..4127d1e
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed.9.png b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
new file mode 100644
index 0000000..525ab8a
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
new file mode 100644
index 0000000..eb05820
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
new file mode 100644
index 0000000..416b2c7
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable/lockscreen_password_field_dark.xml b/core/res/res/drawable/lockscreen_password_field_dark.xml
new file mode 100644
index 0000000..92ceb79
--- /dev/null
+++ b/core/res/res/drawable/lockscreen_password_field_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/textfield_bg_default_holo_dark" />
+    <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_bg_disabled_holo_dark" />
+    <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_bg_activated_holo_dark" />
+    <iten android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_bg_focused_holo_dark" />
+    <item android:state_enabled="true" android:drawable="@drawable/textfield_bg_default_holo_dark" />
+    <item android:state_focused="true" android:drawable="@drawable/textfield_bg_disabled_focused_holo_dark" />
+    <item android:drawable="@drawable/textfield_bg_disabled_holo_dark" />
+</selector>
+
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
index 4bc7292..5ea43dc 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
@@ -20,76 +20,88 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="horizontal"
-        >
+    android:orientation="vertical">
 
-    <!-- left side: status -->
-    <RelativeLayout
-        android:layout_height="match_parent"
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
         android:layout_weight="1"
-        android:layout_width="0dip">
+    />
 
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <!-- left side: status -->
         <include layout="@layout/keyguard_screen_status_land"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="102dip"
-            android:layout_marginTop="320dip"
-            android:layout_alignParentTop="true"
+            android:paddingTop="50dip"
+            android:layout_centerVertical="true"
             android:layout_alignParentLeft="true"/>
 
+        <!-- right side: password -->
+        <LinearLayout
+            android:layout_width="330dip"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="155dip">
+
+            <!-- Password entry field -->
+            <EditText android:id="@+id/passwordEntry"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:singleLine="true"
+                android:textStyle="normal"
+                android:inputType="textPassword"
+                android:gravity="center"
+                android:textSize="24sp"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:background="@drawable/lockscreen_password_field_dark"
+                android:textColor="#ffffffff"
+                />
+
+            <!-- Numeric keyboard -->
+            <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+                android:layout_width="330dip"
+                android:layout_height="330dip"
+                android:background="#00000000"
+                android:layout_marginTop="5dip"
+                android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+                android:visibility="gone"
+            />
+        </LinearLayout>
+
     </RelativeLayout>
 
-    <!-- right side: password -->
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
         android:layout_weight="1"
-        android:gravity="center">
+    />
 
-        <!-- Password entry field -->
-        <EditText android:id="@+id/passwordEntry"
-            android:layout_height="wrap_content"
-            android:layout_width="330dip"
-            android:singleLine="true"
-            android:textStyle="normal"
-            android:inputType="textPassword"
-            android:gravity="center"
-            android:layout_gravity="center"
-            android:textSize="24sp"
-            android:layout_marginTop="120dip"
-            android:layout_marginBottom="5dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:background="@drawable/password_field_default"
-            android:textColor="#ffffffff"
-            />
+    <!-- Alphanumeric keyboard -->
+    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="#00000000"
+        android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+        android:visibility="gone"
+    />
 
-        <!-- Numeric keyboard -->
-        <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
-            android:layout_width="330dip"
-            android:layout_height="260dip"
-            android:background="#00000000"
-            android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
-        />
-        <!-- Alphanumeric keyboard -->
-        <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
-            android:layout_width="450dip"
-            android:layout_height="230dip"
-            android:background="#00000000"
-            android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
-        />
+    <!-- emergency call button NOT CURRENTLY USED -->
+    <Button
+        android:id="@+id/emergencyCall"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:drawableLeft="@drawable/ic_emergency"
+        android:drawablePadding="8dip"
+        android:text="@string/lockscreen_emergency_call"
+        android:visibility="gone"
+        style="@style/Widget.Button.Transparent"
+    />
 
-        <!-- emergency call button -->
-        <Button
-            android:id="@+id/emergencyCall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:drawableLeft="@drawable/ic_emergency"
-            android:drawablePadding="8dip"
-            android:text="@string/lockscreen_emergency_call"
-            android:visibility="gone"
-            style="@style/Widget.Button.Transparent"
-        />
-
-    </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
index e63fb9b..8a059f5 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
@@ -56,7 +56,7 @@
             android:layout_marginTop="120dip"
             android:layout_marginBottom="5dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:background="@drawable/password_field_default"
+            android:background="@drawable/lockscreen_password_field_dark"
             android:textColor="#ffffffff"
             />
 
@@ -69,7 +69,7 @@
         />
         <!-- Alphanumeric keyboard -->
         <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
-            android:layout_width="450dip"
+            android:layout_width="match_parent"
             android:layout_height="230dip"
             android:background="#00000000"
             android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
diff --git a/core/res/res/values-xlarge-land/dimens.xml b/core/res/res/values-xlarge-land/dimens.xml
index 6a2b93f..0b43a42 100644
--- a/core/res/res/values-xlarge-land/dimens.xml
+++ b/core/res/res/values-xlarge-land/dimens.xml
@@ -17,6 +17,9 @@
 */
 -->
 <resources>
+    <!-- Default height of a key in the password keyboard for alpha -->
+    <dimen name="password_keyboard_key_height_alpha">100dip</dimen>
+    <dimen name="password_keyboard_key_height_numeric">75dip</dimen>
     <!-- Minimum width of the search view text entry area. -->
     <dimen name="search_view_text_min_width">256dip</dimen>
 </resources>
diff --git a/core/res/res/values-xlarge/dimens.xml b/core/res/res/values-xlarge/dimens.xml
index 5b0ea30..63d3619 100644
--- a/core/res/res/values-xlarge/dimens.xml
+++ b/core/res/res/values-xlarge/dimens.xml
@@ -24,15 +24,17 @@
     <dimen name="status_bar_icon_size">32dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
-    
+
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <!-- Margin for permanent screen decorations at the bottom. -->
     <dimen name="screen_margin_bottom">48dip</dimen>
-    
+
     <!-- Default height of a key in the password keyboard for alpha -->
-    <dimen name="password_keyboard_key_height_alpha">0.35in</dimen>
+    <dimen name="password_keyboard_key_height_alpha">75dip</dimen>
     <!-- Default height of a key in the password keyboard for numeric -->
-    <dimen name="password_keyboard_key_height_numeric">0.47in</dimen>
+    <dimen name="password_keyboard_key_height_numeric">75dip</dimen>
+    <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
+    <dimen name="password_keyboard_height">48.0mm</dimen>
 
     <!-- The width that is used when creating thumbnails of applications. -->
     <dimen name="thumbnail_width">230dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9a1b42d..46e45db 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2677,4 +2677,11 @@
     <string name="sync_undo_deletes">Undo the deletes.</string>
     <!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to do nothing for now -->
     <string name="sync_do_nothing">Do nothing for now.</string>
+
+    <!-- Title of the VPN service notification: VPN connected [CHAR LIMIT=NONE] -->
+    <string name="vpn_notification_title_connected"><xliff:g id="profilename" example="Home PPTP">%s</xliff:g> VPN connected</string>
+    <!-- Title of the VPN service notification: VPN disconnected [CHAR LIMIT=NONE] -->
+    <string name="vpn_notification_title_disconnected"><xliff:g id="profilename" example="Home PPTP">%s</xliff:g> VPN disconnected</string>
+    <!-- Message of the VPN service notification: Hint to reconnect VPN [CHAR LIMIT=NONE] -->
+    <string name="vpn_notification_hint_disconnected">Touch to reconnect to a VPN.</string>
 </resources>
diff --git a/core/res/res/xml-xlarge/password_kbd_qwerty.xml b/core/res/res/xml-xlarge/password_kbd_qwerty.xml
index 0a35040..fd1d5f1 100755
--- a/core/res/res/xml-xlarge/password_kbd_qwerty.xml
+++ b/core/res/res/xml-xlarge/password_kbd_qwerty.xml
@@ -2,7 +2,7 @@
 <!--
 /*
 **
-** Copyright 2008, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -19,26 +19,15 @@
 -->
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
-    android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:keyWidth="8.272%p"
+    keyboardHeight="@dimen/password_keyboard_height"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
-    >
+    android:horizontalGap="0px"
+    android:verticalGap="0px">
 
-    <Row android:rowEdgeFlags="top">
-        <Key android:keyLabel="1" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="2"/>
-        <Key android:keyLabel="3"/>
-        <Key android:keyLabel="4"/>
-        <Key android:keyLabel="5"/>
-        <Key android:keyLabel="6"/>
-        <Key android:keyLabel="7"/>
-        <Key android:keyLabel="8"/>
-        <Key android:keyLabel="9"/>
-        <Key android:keyLabel="0" android:keyEdgeFlags="right"/>
-    </Row>
-
-    <Row>
+    <Row android:keyWidth="8.272%p">
+        <Key android:keyLabel="Tab"
+            android:codes="9"/>
         <Key android:keyLabel="q" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="w"/>
         <Key android:keyLabel="e"/>
@@ -48,12 +37,21 @@
         <Key android:keyLabel="u"/>
         <Key android:keyLabel="i"/>
         <Key android:keyLabel="o"/>
-        <Key android:keyLabel="p" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="p"/>
+        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+            android:codes="-5"
+            android:keyWidth="9.331%p"
+            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            android:isRepeatable="true"
+            android:keyEdgeFlags="right"/>
     </Row>
 
-    <Row>
-        <Key android:keyLabel="a" android:horizontalGap="5%p"
+    <Row android:keyWidth="8.157%p">
+        <Key android:codes="-2"
+            android:keyLabel="@string/password_keyboard_label_symbol_key"
+            android:keyWidth="11.167%p"
             android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="a"/>
         <Key android:keyLabel="s"/>
         <Key android:keyLabel="d"/>
         <Key android:keyLabel="f"/>
@@ -61,14 +59,22 @@
         <Key android:keyLabel="h"/>
         <Key android:keyLabel="j"/>
         <Key android:keyLabel="k"/>
-        <Key android:keyLabel="l" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="l"/>
+        <Key android:codes="10"
+            android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
+            android:keyWidth="15.750%p"
+            android:keyEdgeFlags="right"/>
     </Row>
 
-    <Row>
-        <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
-            android:keyWidth="15%p" android:isModifier="true"
+    <Row android:keyWidth="8.042%p">
+        <Key android:codes="-1"
+            android:keyIcon="@drawable/sym_keyboard_shift"
+            android:keyWidth="15.192%p"
+            android:isModifier="true"
             android:iconPreview="@drawable/sym_keyboard_feedback_shift"
-            android:isSticky="true" android:keyEdgeFlags="left"/>
+            android:isSticky="true"
+            android:keyEdgeFlags="left"/>
         <Key android:keyLabel="z"/>
         <Key android:keyLabel="x"/>
         <Key android:keyLabel="c"/>
@@ -76,26 +82,26 @@
         <Key android:keyLabel="b"/>
         <Key android:keyLabel="n"/>
         <Key android:keyLabel="m"/>
-        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
-            android:keyWidth="15%p" android:keyEdgeFlags="right"
-            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
-            android:isRepeatable="true"/>
+        <Key android:keyLabel="," />
+        <Key android:keyLabel="." />
+        <Key android:codes="-1"
+            android:keyIcon="@drawable/sym_keyboard_shift"
+            android:keyWidth="12.530%p"
+            android:isModifier="true"
+            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
+            android:isSticky="true"
+            android:keyEdgeFlags="right"/>
     </Row>
 
-    <Row android:keyboardMode="@+id/mode_normal" android:rowEdgeFlags="bottom">
-        <Key android:codes="-2" android:keyLabel="@string/password_keyboard_label_symbol_key"
-            android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," />
-        <Key android:keyLabel="-" />
-        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
+    <Row android:keyWidth="8.042%p"
+        android:keyboardMode="@+id/mode_normal">
+        <Key android:keyLabel="/" android:horizontalGap="24.126%p"/>
+        <Key android:codes="32"
+            android:keyIcon="@drawable/sym_keyboard_space"
             android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:keyWidth="20%p"/>
-        <Key android:keyLabel="=" />
-        <Key android:keyLabel="."
-            android:keyWidth="10%p"/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
-            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
-            android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+            android:keyWidth="37.454%p"/>
+        <Key android:keyLabel="'" />
+        <Key android:keyLabel="-" />
     </Row>
 
 </Keyboard>
diff --git a/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml b/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
index 9e9db81..671d87f 100755
--- a/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
@@ -2,7 +2,7 @@
 <!--
 /*
 **
-** Copyright 2008, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -19,82 +19,89 @@
 -->
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
-    android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:keyWidth="8.272%p"
+    keyboardHeight="@dimen/password_keyboard_height"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
-    >
+    android:horizontalGap="0px"
+    android:verticalGap="0px">
 
-    <Row android:rowEdgeFlags="top">
-        <Key android:keyLabel="\@" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="\#"/>
-        <Key android:keyLabel="$"/>
-        <Key android:keyLabel="%"/>
-        <Key android:keyLabel="&amp;"/>
-        <Key android:keyLabel="*"/>
-        <Key android:keyLabel="-"/>
-        <Key android:keyLabel="+"/>
-        <Key android:keyLabel="("/>
-        <Key android:keyLabel=")" android:keyEdgeFlags="right"/>
-    </Row>
-
-    <Row>
-        <Key android:keyLabel="q" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="w"/>
-        <Key android:keyLabel="e"/>
-        <Key android:keyLabel="r"/>
-        <Key android:keyLabel="t"/>
-        <Key android:keyLabel="y"/>
-        <Key android:keyLabel="u"/>
-        <Key android:keyLabel="i"/>
-        <Key android:keyLabel="o"/>
-        <Key android:keyLabel="p" android:keyEdgeFlags="right"/>
-    </Row>
-
-    <Row>
-        <Key android:keyLabel="a" android:horizontalGap="5%p"
-            android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="s"/>
-        <Key android:keyLabel="d"/>
-        <Key android:keyLabel="f"/>
-        <Key android:keyLabel="g"/>
-        <Key android:keyLabel="h"/>
-        <Key android:keyLabel="j"/>
-        <Key android:keyLabel="k"/>
-        <Key android:keyLabel="l" android:keyEdgeFlags="right"/>
-    </Row>
-
-    <Row>
-        <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
-            android:keyWidth="15%p" android:isModifier="true"
-            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
-            android:isSticky="true" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="z"/>
-        <Key android:keyLabel="x"/>
-        <Key android:keyLabel="c"/>
-        <Key android:keyLabel="v"/>
-        <Key android:keyLabel="b"/>
-        <Key android:keyLabel="n"/>
-        <Key android:keyLabel="m"/>
-        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
-            android:keyWidth="15%p" android:keyEdgeFlags="right"
+    <Row android:keyWidth="8.272%p">
+        <Key android:keyLabel="Tab"
+            android:codes="9"/>
+        <Key android:keyLabel="Q" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="W"/>
+        <Key android:keyLabel="E"/>
+        <Key android:keyLabel="R"/>
+        <Key android:keyLabel="T"/>
+        <Key android:keyLabel="Y"/>
+        <Key android:keyLabel="U"/>
+        <Key android:keyLabel="I"/>
+        <Key android:keyLabel="O"/>
+        <Key android:keyLabel="P"/>
+        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+            android:codes="-5"
+            android:keyWidth="9.331%p"
             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
-            android:isRepeatable="true"/>
+            android:isRepeatable="true"
+            android:keyEdgeFlags="right"/>
     </Row>
 
-    <Row android:keyboardMode="@+id/mode_normal" android:rowEdgeFlags="bottom">
-        <Key android:codes="-2" android:keyLabel="@string/password_keyboard_label_symbol_key"
-            android:keyWidth="20%p" android:keyEdgeFlags="left"/>
-        <Key android:keyLabel="," />
-        <Key android:keyLabel="_" />
-        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:keyWidth="20%p"/>
-        <Key android:keyLabel="+" />
-        <Key android:keyLabel="."/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+    <Row android:keyWidth="8.157%p">
+        <Key android:codes="-2"
+            android:keyLabel="@string/password_keyboard_label_symbol_key"
+            android:keyWidth="11.167%p"
+            android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="A"/>
+        <Key android:keyLabel="S"/>
+        <Key android:keyLabel="D"/>
+        <Key android:keyLabel="F"/>
+        <Key android:keyLabel="G"/>
+        <Key android:keyLabel="H"/>
+        <Key android:keyLabel="J"/>
+        <Key android:keyLabel="K"/>
+        <Key android:keyLabel="L"/>
+        <Key android:codes="10"
+            android:keyIcon="@drawable/sym_keyboard_ok"
             android:iconPreview="@drawable/sym_keyboard_feedback_ok"
-            android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+            android:keyWidth="15.750%p"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.042%p">
+        <Key android:codes="-1"
+            android:keyIcon="@drawable/sym_keyboard_shift"
+            android:keyWidth="15.192%p"
+            android:isModifier="true"
+            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
+            android:isSticky="true"
+            android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="Z"/>
+        <Key android:keyLabel="X"/>
+        <Key android:keyLabel="C"/>
+        <Key android:keyLabel="V"/>
+        <Key android:keyLabel="B"/>
+        <Key android:keyLabel="N"/>
+        <Key android:keyLabel="M"/>
+        <Key android:keyLabel="!" />
+        <Key android:keyLabel="\?" />
+        <Key android:codes="-1"
+            android:keyIcon="@drawable/sym_keyboard_shift"
+            android:keyWidth="12.530%p"
+            android:isModifier="true"
+            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
+            android:isSticky="true"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.042%p"
+        android:keyboardMode="@+id/mode_normal">
+        <Key android:keyLabel="\@" android:horizontalGap="24.126%p"/>
+        <Key android:codes="32"
+            android:keyIcon="@drawable/sym_keyboard_space"
+            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+            android:keyWidth="37.454%p"/>
+        <Key android:keyLabel="&quot;" />
+        <Key android:keyLabel="_" />
     </Row>
 
 </Keyboard>
diff --git a/core/res/res/xml-xlarge/password_kbd_symbols.xml b/core/res/res/xml-xlarge/password_kbd_symbols.xml
new file mode 100755
index 0000000..5ae5577
--- /dev/null
+++ b/core/res/res/xml-xlarge/password_kbd_symbols.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="8.272%p"
+    keyboardHeight="@dimen/password_keyboard_height"
+    android:keyHeight="@dimen/password_keyboard_key_height_alpha"
+    android:horizontalGap="0px"
+    android:verticalGap="0px">
+
+    <Row android:keyWidth="8.272%p">
+        <Key android:keyLabel="Tab"
+            android:codes="9"/>
+        <Key android:keyLabel="1" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="2"/>
+        <Key android:keyLabel="3"/>
+        <Key android:keyLabel="4"/>
+        <Key android:keyLabel="5"/>
+        <Key android:keyLabel="6"/>
+        <Key android:keyLabel="7"/>
+        <Key android:keyLabel="8"/>
+        <Key android:keyLabel="9"/>
+        <Key android:keyLabel="0"/>
+        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+            android:codes="-5"
+            android:keyWidth="9.331%p"
+            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            android:isRepeatable="true"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.157%p">
+        <Key android:codes="-2"
+            android:keyLabel="@string/password_keyboard_label_alpha_key"
+            android:keyWidth="11.167%p"
+            android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="\#"/>
+        <Key android:keyLabel="$"/>
+        <Key android:keyLabel="%"/>
+        <Key android:keyLabel="&amp;"/>
+        <Key android:keyLabel="*"/>
+        <Key android:keyLabel="-"/>
+        <Key android:keyLabel="+"/>
+        <Key android:keyLabel="("/>
+        <Key android:keyLabel=")"/>
+        <Key android:codes="10"
+            android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
+            android:keyWidth="15.750%p"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.042%p">
+        <Key android:codes="-1"
+            android:keyLabel="@string/password_keyboard_label_alt_key"
+            android:keyWidth="15.192%p"
+            android:isModifier="true"
+            android:isSticky="true"
+            android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="&lt;"/>
+        <Key android:keyLabel="&gt;"/>
+        <Key android:keyLabel="="/>
+        <Key android:keyLabel=":"/>
+        <Key android:keyLabel=";"/>
+        <Key android:keyLabel=","/>
+        <Key android:keyLabel="."/>
+        <Key android:keyLabel="!" />
+        <Key android:keyLabel="\?" />
+        <Key android:codes="-1"
+            android:keyLabel="@string/password_keyboard_label_alt_key"
+            android:keyWidth="12.530%p"
+            android:isModifier="true"
+            android:isSticky="true"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.042%p">
+        <Key android:keyLabel="\@" android:horizontalGap="16.084%p"/>
+        <Key android:keyLabel="/" />
+        <Key android:codes="32"
+            android:keyIcon="@drawable/sym_keyboard_space"
+            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+            android:keyWidth="37.454%p"/>
+        <Key android:keyLabel="\'" />
+        <Key android:keyLabel="-" />
+    </Row>
+
+</Keyboard>
+
diff --git a/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml b/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
new file mode 100755
index 0000000..26ade76
--- /dev/null
+++ b/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="10%p"
+    android:horizontalGap="0px"
+    android:verticalGap="0px"
+    android:keyHeight="@dimen/password_keyboard_key_height_alpha">
+
+    <Row android:keyWidth="8.272%p"
+        android:rowEdgeFlags="top">
+        <Key android:keyLabel="Tab" android:codes="9"/>
+        <Key android:keyLabel="~" />
+        <Key android:keyLabel="`" />
+        <Key android:keyLabel="|" />
+        <Key android:keyLabel="•" />
+        <Key android:keyLabel="√" />
+        <Key android:keyLabel="π" />
+        <Key android:keyLabel="÷" />
+        <Key android:keyLabel="×" />
+        <Key android:keyLabel="§" />
+        <Key android:keyLabel="Δ" />
+        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+            android:codes="-5"
+            android:keyWidth="9.331%p"
+            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
+            android:isRepeatable="true"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.157%p">
+        <Key android:codes="-2"
+            android:keyLabel="@string/password_keyboard_label_alpha_key"
+            android:keyWidth="11.167%p"
+            android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="£" />
+        <Key android:keyLabel="¢" />
+        <Key android:keyLabel="€" />
+        <Key android:keyLabel="¥" />
+        <Key android:keyLabel="^"/>
+        <Key android:keyLabel="°" />
+        <Key android:keyLabel="±" />
+        <Key android:keyLabel="{" />
+        <Key android:keyLabel="}" />
+        <Key android:codes="10"
+            android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
+            android:keyWidth="15.750%p"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:keyWidth="8.042%p">
+        <Key android:codes="-1"
+            android:keyLabel="@string/password_keyboard_label_alt_key"
+            android:keyWidth="15.192%p"
+            android:isModifier="true"
+            android:isSticky="true"
+            android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="\\" />
+        <Key android:keyLabel="©" />
+        <Key android:keyLabel="®" />
+        <Key android:keyLabel="™" />
+        <Key android:keyLabel="℅" />
+        <Key android:keyLabel="[" />
+        <Key android:keyLabel="]" />
+        <Key android:keyLabel="¡" />
+        <Key android:keyLabel="¿" />
+        <Key android:codes="-1"
+            android:keyLabel="@string/password_keyboard_label_alt_key"
+            android:keyWidth="12.530%p"
+            android:isModifier="true"
+            android:isSticky="true"
+            android:keyEdgeFlags="right"/>
+    </Row>
+
+    <!-- This row is intentionally not marked as a bottom row -->
+    <Row android:keyWidth="8.042%p">
+        <Key android:codes="32" android:horizontalGap="32.168%p"
+            android:keyIcon="@drawable/sym_keyboard_space"
+            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+            android:keyWidth="37.454%p"/>
+    </Row>
+</Keyboard>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 67f1fec..270d153 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -213,6 +213,9 @@
           <li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html">
                 <span class="en">3D with OpenGL</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html">
+                <span class="en">Animation</span>
+              </a><span class="new">new!</span></li>
         </ul>
       </li>
       <li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd
index 05f4023..6594568 100644
--- a/docs/html/guide/topics/graphics/2d-graphics.jd
+++ b/docs/html/guide/topics/graphics/2d-graphics.jd
@@ -17,8 +17,6 @@
       <li><a href="#shape-drawable">Shape Drawable</a></li>
    <!--   <li><a href="#state-list">StateListDrawable</a></li> -->
       <li><a href="#nine-patch">Nine-patch</a></li>
-      <li><a href="#tween-animation">Tween Animation</a></li>
-      <li><a href="#frame-animation">Frame Animation</a></li>
     </ol>
   </div>
 </div>
@@ -328,172 +326,4 @@
 stretches to accommodate it.
 </p>
 
-<img src="{@docRoot}images/ninepatch_examples.png" alt=""/>
-
-
-<h2 id="tween-animation">Tween Animation</h2>
-
-<p>A tween animation can perform a series of simple transformations (position, size, rotation, and transparency) on
-the contents of a View object. So, if you have a TextView object, you can move, rotate, grow, or shrink the text. 
-If it has a background image, the background image will be transformed along with the text.
-The {@link android.view.animation animation package} provides all the classes used in a tween animation.</p>
-
-<p>A sequence of animation instructions defines the tween animation, defined by either XML or Android code.
-Like defining a layout, an XML file is recommended because it's more readable, reusable, and swappable 
-than hard-coding the animation. In the example below, we use XML. (To learn more about defining an animation 
-in your application code, instead of XML, refer to the 
-{@link android.view.animation.AnimationSet} class and other {@link android.view.animation.Animation} subclasses.)</p>
-
-<p>The animation instructions define the transformations that you want to occur, when they will occur, 
-and how long they should take to apply. Transformations can be sequential or simultaneous &mdash;
-for example, you can have the contents of a TextView move from left to right, and then 
-rotate 180 degrees, or you can have the text move and rotate simultaneously. Each transformation 
-takes a set of parameters specific for that transformation (starting size and ending size
-for size change, starting angle and ending angle for rotation, and so on), and
-also a set of common parameters (for instance, start time and duration). To make
-several transformations happen simultaneously, give them the same start time;
-to make them sequential, calculate the start time plus the duration of the preceding transformation.
-</p>
-
-<p>The animation XML file belongs in the <code>res/anim/</code> directory of your Android project.
-The file must have a single root element: this will be either a single <code>&lt;alpha&gt;</code>,
-<code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>, <code>&lt;rotate&gt;</code>, interpolator element, 
-or <code>&lt;set&gt;</code> element that holds groups of these elements (which may include another
-<code>&lt;set&gt;</code>). By default, all animation instructions are applied simultaneously. 
-To make them occur sequentially, you must specify the <code>startOffset</code> attribute, as shown in the example below.
-</p>
-
-<p>The following XML from one of the ApiDemos is used to stretch, 
-then simultaneously spin and rotate a View object.
-</p>
-<pre>
-&lt;set android:shareInterpolator="false"&gt;
-   &lt;scale
-          android:interpolator="&#64;android:anim/accelerate_decelerate_interpolator"
-          android:fromXScale="1.0"
-          android:toXScale="1.4"
-          android:fromYScale="1.0"
-          android:toYScale="0.6"
-          android:pivotX="50%"
-          android:pivotY="50%"
-          android:fillAfter="false"
-          android:duration="700" /&gt;
-   &lt;set android:interpolator="&#64;android:anim/decelerate_interpolator"&gt;
-      &lt;scale
-             android:fromXScale="1.4" 
-             android:toXScale="0.0"
-             android:fromYScale="0.6"
-             android:toYScale="0.0" 
-             android:pivotX="50%" 
-             android:pivotY="50%" 
-             android:startOffset="700"
-             android:duration="400" 
-             android:fillBefore="false" /&gt;
-      &lt;rotate 
-             android:fromDegrees="0" 
-             android:toDegrees="-45"
-             android:toYScale="0.0" 
-             android:pivotX="50%" 
-             android:pivotY="50%"
-             android:startOffset="700"
-             android:duration="400" /&gt;
-   &lt;/set&gt;
-&lt;/set&gt;
-</pre>
-<p>Screen coordinates (not used in this example) are (0,0) at the upper left hand corner, 
-and increase as you go down and to the right.</p>
-
-<p>Some values, such as pivotX, can be specified relative to the object itself or relative to the parent. 
-Be sure to use the proper format for what you want ("50" for 50% relative to the parent, or "50%" for 50% 
-relative to itself).</p>
-
-<p>You can determine how a transformation is applied over time by assigning an 
-{@link android.view.animation.Interpolator}. Android includes 
-several Interpolator subclasses that specify various speed curves: for instance, 
-{@link android.view.animation.AccelerateInterpolator} tells 
-a transformation to start slow and speed up. Each one has an attribute value that can be applied in the XML.</p>
-
-<p>With this XML saved as <code>hyperspace_jump.xml</code> in the <code>res/anim/</code> directory of the
-project, the following Java code will reference it and apply it to an {@link android.widget.ImageView} object
-from the layout.
-</p>
-<pre>
-ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
-Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
-spaceshipImage.startAnimation(hyperspaceJumpAnimation);
-</pre>
-
-<p>As an alternative to <code>startAnimation()</code>, you can define a starting time for the animation with
-<code>{@link android.view.animation.Animation#setStartTime(long) Animation.setStartTime()}</code>, 
-then assign the animation to the View with
-<code>{@link android.view.View#setAnimation(android.view.animation.Animation) View.setAnimation()}</code>.
-</p>
-
-<p>For more information on the XML syntax, available tags and attributes, see <a
-href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
-
-<p class="note"><strong>Note:</strong> Regardless of how your animation may move or resize, the bounds of the 
-View that holds your animation will not automatically adjust to accommodate it. Even so, the animation will still
-be drawn beyond the bounds of its View and will not be clipped. However, clipping <em>will occur</em>
-if the animation exceeds the bounds of the parent View.</p>
-
-
-<h2 id="frame-animation">Frame Animation</h2>
-
-<p>This is a traditional animation in the sense that it is created with a sequence of different
-images, played in order, like a roll of film. The {@link android.graphics.drawable.AnimationDrawable}
-class is the basis for frame animations.</p>
-
-<p>While you can define the frames of an animation in your code, using the 
-{@link android.graphics.drawable.AnimationDrawable} class API, it's more simply accomplished with a single XML 
-file that lists the frames that compose the animation. Like the tween animation above, the XML file for this kind 
-of animation belongs in the <code>res/drawable/</code> directory of your Android project. In this case,
-the instructions are the order and duration for each frame of the animation.</p>
-
-<p>The XML file consists of an <code>&lt;animation-list></code> element as the root node and a series
-of child <code>&lt;item></code> nodes that each define a frame: a drawable resource for the frame and the frame duration.
-Here's an example XML file for a frame-by-frame animation:</p>
-<pre>
-&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
-    android:oneshot="true">
-    &lt;item android:drawable="&#64;drawable/rocket_thrust1" android:duration="200" />
-    &lt;item android:drawable="&#64;drawable/rocket_thrust2" android:duration="200" />
-    &lt;item android:drawable="&#64;drawable/rocket_thrust3" android:duration="200" />
-&lt;/animation-list>
-</pre>
-
-<p>This animation runs for just three frames. By setting the <code>android:oneshot</code> attribute of the 
-list to <var>true</var>, it will cycle just once then stop and hold on the last frame. If it is set <var>false</var> then
-the animation will loop. With this XML saved as <code>rocket_thrust.xml</code> in the <code>res/drawable/</code> directory
-of the project, it can be added as the background image to a View and then called to play. Here's an example Activity,
-in which the animation is added to an {@link android.widget.ImageView} and then animated when the screen is touched:</p>
-<pre>
-AnimationDrawable rocketAnimation;
-
-public void onCreate(Bundle savedInstanceState) {
-  super.onCreate(savedInstanceState);
-  setContentView(R.layout.main);
-
-  ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
-  rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
-  rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
-}
-
-public boolean onTouchEvent(MotionEvent event) {
-  if (event.getAction() == MotionEvent.ACTION_DOWN) {
-    rocketAnimation.start();
-    return true;
-  }
-  return super.onTouchEvent(event);
-}
-</pre>
-<p>It's important to note that the <code>start()</code> method called on the AnimationDrawable cannot be
-called during the <code>onCreate()</code> method of your Activity, because the AnimationDrawable is not yet fully attached
-to the window. If you want to play the animation immediately, without
-requiring interaction, then you might want to call it from the 
-<code>{@link android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code> method in 
-your Activity, which will get called when Android brings your window into focus.</p> 
-
-<p>For more information on the XML syntax, available tags and attributes, see <a
-href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
-
+<img src="{@docRoot}images/ninepatch_examples.png" alt=""/>
\ No newline at end of file
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
new file mode 100644
index 0000000..c977d51
--- /dev/null
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -0,0 +1,839 @@
+page.title=Animation
+@jd:body
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li>
+          <a href="#property-animation">Property Animation</a>
+
+          <ol>
+            <li><a href="#value-animator">Animating with ValueAnimator</a></li>
+
+            <li><a href="#object-animator">Animating with ObjectAnimator</a></li>
+
+            <li><a href="#type-evaluator">Using the TypeEvaluator</a></li>
+
+            <li><a href="#interpolators">Using interpolators</a></li>
+
+            <li><a href="#keyframes">Specifying keyframes</a></li>
+
+            <li><a href="#choreography">Choreographing multiple animations with AnimatorSet</a></li>
+
+            <li><a href="#declaring-xml">Declaring animations in XML</a></li>
+          </ol>
+        </li>
+
+        <li>
+          <a href="#view-animation">View Animation</a>
+
+          <ol>
+            <li><a href="#tween-animation">Tween animation</a></li>
+
+            <li><a href="#frame-animation">Frame animation</a></li>
+          </ol>
+        </li>
+      </ol>
+
+      <h2>Key classes</h2>
+
+      <ol>
+        <li><code><a href=
+        "/reference/android/animation/ValueAnimator.html">ValueAnimator</a></code></li>
+
+        <li><code><a href=
+        "/reference/android/animation/ObjectAnimator.html">ObjectAnimator</a></code></li>
+
+        <li><code><a href=
+        "/reference/android/animation/TypeEvaluator.html">TypeEvaluator</a></code></li>
+      </ol>
+
+      <h2>Related samples</h2>
+
+      <ol>
+        <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API Demos</a></li>
+      </ol>
+
+    </div>
+  </div>
+
+  <p>The Android system provides a flexible animation system that allows you to animate
+  almost anything, either programmatically or declaratively with XML. There are two
+  animation systems that you can choose from: <a href="property-animation">property
+  animation</a> and <a href="#view-animation">view animation</a>. You can use whichever
+  system that matches your needs, but use only one system for each object that you
+  are animating.</p>
+
+  <h2 id="property-animation">Property Animation</h2>
+
+  <p>Introduced in Android 3.0, the property animation system allows you to animate
+  object properties of any type. <code>int</code>, <code>float</code>, 
+  and hexadecimal color values are supported by default. You can animate any other type by telling the
+  system how to calculate the values for that given type.</p>
+  
+  <p>The property animation system allows you to define many aspects of an animation,
+  such as:</p>
+
+  <ul>
+    <li>Duration</li>
+
+    <li>Repeat amount and behavior</li>
+
+    <li>Type of time interpolation</li>
+
+    <li>Animator sets to play animations together, sequentially, or after specified
+    delays</li>
+
+    <li>Frame refresh delay</li>
+    
+  </ul>
+
+  <p>Most of the property animation system's features can be found in
+  {@link android.animation android.animation}. Because the 
+  <a href="#view-animation>view animation</a> system already
+  defines many interpolators in {@link android.view.animation android.view.animation},
+  you will use those to define your animation's interpolation in the property animation
+  system as well.
+  </p>
+
+  <p>The following items are the main components of the property animation system:</p>
+
+  <dl>
+    <dt><strong>Animators</strong></dt>
+
+    <dd>
+      The {@link android.animation.Animator} class provides the basic structure for
+      creating animations. You normally do not use this class directly as it only provides
+      minimal functionality that must be extended to fully support animating values. 
+      The following subclasses extend {@link android.animation.Animator}, which you might find more useful:
+
+      <ul>
+        <li>{@link android.animation.ValueAnimator} is the main timing engine for
+        property animation and computes the values for the property to be animated.
+        {@link android.animation.ValueAnimator} only computes the animation values and is
+        not aware of the specific object and property that is being animated or what the
+        values might be used for. You must listen for updates to values calculated by the
+        {@link android.animation.ValueAnimator} and process the data with your own logic.
+        See the section about <a href="#value-animator">Animating with ValueAnimator</a>
+        for more information.</li>
+
+        <li>{@link android.animation.ObjectAnimator} is a subclass of {@link
+        android.animation.ValueAnimator} and allows you to set a target object and object
+        property to animate. This class is aware of the object and property to be
+        animated, and updates the property accordingly when it computes a new value for
+        the animation. See the section about <a href="#object-animator">
+        Animating with ObjectAnimator</a> for more information.</li>
+
+        <li>{@link android.animation.AnimatorSet} provides a mechanism to group
+        animations together so that they are rendered in relation to one another. You can
+        set animations to play together, sequentially, or after a specified delay.
+        See the section about <a href="#choreography">
+        Choreographing multiple animations with Animator Sets</a> for more information.</li>
+      </ul>
+    </dd>
+
+    <dt><strong>Evaluators</strong></dt>
+
+    <dd>
+      <p>If you are animating an object property that is <em>not</em> an <code>int</code>,
+      <code>float</code>, or color, implement the {@link android.animation.TypeEvaluator}
+      interface to specify how to compute the object property's animated values. You give
+      a {@link android.animation.TypeEvaluator} the timing data that is provided by an
+      {@link android.animation.Animator} class, the animation's start and end value, and
+      provide logic that computes the animated values of the property based on this data.</p>
+
+      <p>You can also specify a custom {@link android.animation.TypeEvaluator} for
+      <code>int</code>, <code>float</code>, and color values as well, if you want to
+      process those types differently than the default behavior.</p>
+
+      <p>See <a href="#type-evaluator">Using a TypeEvaluator</a> for more information on
+      how to write a custom evaluator.</p>
+    </dd>
+
+    <dt><strong>Interpolators</strong></dt>
+
+    <dd>
+      <p>A time interpolator defines how specific values in an animation are calculated
+      as a function of time. For example, you can specify animations to happen linearly
+      across the whole animation, meaning the animation moves evenly the entire time, or
+      you can specify animations to use non-linear time, for example, using acceleration
+      or deceleration at the beginning or end of the animation.</p>
+
+      <p>The Android system provides a set of common interpolators in
+      {@link android.view.animation android.view.animation}. If none of these suits your needs, you
+      can implement the {@link android.animation.TimeInterpolator} interface and create
+      your own. See <a href="#interpolators">Interpolators</a> for more information on
+      how to write a custom interpolator.</p>
+    </dd>
+  </dl>
+  
+    
+  <p>The <code>com.example.android.apis.animation</code> package in the <a href=
+  "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">
+  API Demos</a> sample project also provides a good overview and many examples on how to
+  use the property animation system.</p>
+
+
+  <h3>How the property animation system calculates animated values</h3>
+
+  <p>When you call {@link android.animation.ValueAnimator#start start()} to begin an animation,
+  the {@link android.animation.ValueAnimator} calculates
+  an <em>elapsed fraction</em> between 0 and 1, based on the duration of the animation
+  and how much time has elapsed. The elapsed fraction represents the percentage of time
+  that the animation has completed, 0 meaning 0% and 1 meaning 100%. The Animator then
+  calls the {@link android.animation.TimeInterpolator} that is currently set, 
+  to calculate an <em>eased fraction</em>,
+  which is a modified value of the elapsed fraction that takes into account the interpolator that
+  is set (time interpolation is often referred to as <em>easing</em>). The eased fraction
+  is the final value that is used to animate the property.</p>
+
+  <p>Once the eased fraction is calculated, {@link android.animation.ValueAnimator} calls
+  the appropriate {@link android.animation.TypeEvaluator} to calculate the final value of
+  the property that you are animating, based on the eased fraction, the starting value,
+  and ending value of the animation.</p>
+
+  <h3 id="value-animator">Animating with ValueAnimator</h3>
+
+  <p>The {@link android.animation.ValueAnimator} class lets you animate values of some
+  type for the duration of an animation by specifying a set of <code>int</code>,
+  <code>float</code>, or color values to animate over and the duration of the animation.
+  You obtain a {@link android.animation.ValueAnimator} by calling one of its factory
+  methods: {@link android.animation.ValueAnimator#ofInt ofInt()},
+  {@link android.animation.ValueAnimator#ofFloat ofFloat()},
+  or {@link android.animation.ValueAnimator#ofObject ofObject()}. For example:</p>
+  
+  <pre>ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
+animation.setDuration(1000);
+animation.start();        
+</pre>
+
+  <p>In this code, the {@link android.animation.ValueAnimator} starts
+  calculating the values of the animation, between 0 and 1, for
+  a duration of 1000 ms, when the <code>start()</code> method runs.</p>
+
+  <p>You can also specify a custom type to animate by doing the following:</p>
+  
+  <pre>ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
+animation.setDuration(1000);
+animation.start();        
+</pre>
+
+  <p>In this code, the {@link android.animation.ValueAnimator} starts
+  calculating the values of the animation, between <code>startPropertyValue</code> and
+  <code>endPropertyValue</code> using the logic supplied by <code>MyTypeEvaluator</code>
+  for a duration of 1000 ms, when the {@link android.animation.ValueAnimator#start start()}
+  method runs.</p>
+
+  <p>The previous code snippets, however, do not affect an object, because the {@link
+  android.animation.ValueAnimator} does not operate on objects or properties directly. To
+  use the results of a {@link android.animation.ValueAnimator}, you must define listeners
+  in the {@link android.animation.ValueAnimator} to appropriately handle important events
+  during the animation's lifespan, such as frame updates. You can implement the following
+  interfaces to create listeners for {@link android.animation.ValueAnimator}:</p>
+
+  <ul>
+    <li>{@link android.animation.Animator.AnimatorListener}
+
+      <ul>
+        <li>{@link android.animation.Animator.AnimatorListener#onAnimationStart
+        onAnimationStart()} - Called when the animation starts</li>
+
+        <li>{@link android.animation.Animator.AnimatorListener#onAnimationEnd
+        onAnimationEnd()} - Called when the animation ends.</li>
+
+        <li>{@link android.animation.Animator.AnimatorListener#onAnimationRepeat
+        onAnimationRepeat()} - Called when the animation repeats itself.</li>
+
+        <li>{@link android.animation.Animator.AnimatorListener#onAnimationCancel
+        onAnimationCancel()} - Called when the animation is canceled.</li>
+      </ul>
+    </li>
+
+    <li>{@link android.animation.ValueAnimator.AnimatorUpdateListener}
+
+      <ul>
+        <li>
+          <p>{@link
+          android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate
+          onAnimationUpdate()} - called on every frame of the animation.
+          Listen to this event to use the calculated values generated by
+          {@link android.animation.ValueAnimator} during an animation. To use the value,
+          query the {@link android.animation.ValueAnimator} object passed into the event
+          to get the current animated value with the 
+          {@link android.animation.ValueAnimator#getAnimatedValue getAnimatedValue()} method.</p>
+
+          <p>If you are animating your own custom object (not View objects), this
+          callback must also call the {@link android.view.View#invalidate invalidate()}
+          method to force a redraw of the screen. If you are animating View objects,
+          {@link android.view.View#invalidate invalidate()} is automatically called when
+          a property of the View is changed.</p>
+        </li>
+      </ul>
+
+      <p>You can extend the {@link android.animation.AnimatorListenerAdapter} class
+      instead of implementing the {@link android.animation.Animator.AnimatorListener}
+      interface, if you do not want to implement all of the methods of the {@link
+      android.animation.Animator.AnimatorListener} interface. The {@link
+      android.animation.AnimatorListenerAdapter} class provides empty implementations of the
+      methods that you can choose to override.</p>
+    </li>
+  </ul>
+
+  <p>For example, the <a href=
+  "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
+  Bouncing Balls</a> sample in the API demos creates an {@link
+  android.animation.AnimatorListenerAdapter} for just the {@link
+  android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
+  callback:</p>
+  <pre>ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
+fadeAnim.setDuration(250);
+fadeAnim.addListener(new AnimatorListenerAdapter() {
+public void onAnimationEnd(Animator animation) {
+    balls.remove(((ObjectAnimator)animation).getTarget());
+}
+  
+</pre>
+
+  <h3 id="object-animator">Animating with ObjectAnimator</h3>
+
+  <p>The {@link android.animation.ObjectAnimator} is a subclass of the {@link
+  android.animation.ValueAnimator} (discussed in the previous section)
+  and combines the timing engine and value computation
+  of {@link android.animation.ValueAnimator} with the ability to animate a named property
+  of a target object. This makes animating any object much easier, as you no longer need
+  to implement the {@link android.animation.ValueAnimator.AnimatorUpdateListener}, because
+  the animated property updates automatically.</p>
+
+  <p>Instantiating an {@link android.animation.ObjectAnimator} is similar to a {@link
+  android.animation.ValueAnimator}, but you also specify the object and that object's
+  property (as a String) that you want to animate:</p>
+  <pre>
+ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
+anim.setDuration(1000);
+anim.start();
+</pre>
+
+  <p>To have the {@link android.animation.ObjectAnimator} update properties correctly,
+  you must do the following:</p>
+
+  <ul>
+    <li>The object property that you are animating must have a setter function in the
+    form of <code>set&lt;propertyName&gt;()</code>. Because the {@link
+    android.animation.ObjectAnimator} automatically updates the property during
+    animation, it must be able to access the property with this setter method. For
+    example, if the property name is <code>foo</code>, you need to have a
+    <code>setFoo()</code> method. If this setter method does not exist, you have three
+    options:
+
+      <ul>
+        <li>Add the setter method to the class if you have the rights to do so.</li>
+
+        <li>Use a wrapper class that you have rights to change and have that wrapper
+        receive the value with a valid setter method and forward it to the original
+        object.</li>
+
+        <li>Use {@link android.animation.ValueAnimator} instead.</li>
+      </ul>
+    </li>
+
+    <li>If you specify only one value for the <code>values...</code> parameter,
+    in one of the {@link android.animation.ObjectAnimator} factory methods, it is assumed to be
+    the ending value of the animation. Therefore, the object property that you are
+    animating must have a getter function that is used to obtain the starting value of
+    the animation. The getter function must be in the form of
+    <code>get&lt;propertyName&gt;()</code>. For example, if the property name is
+    <code>foo</code>, you need to have a <code>getFoo()</code> method.</li>
+
+    <li>The getter (if needed) and setter methods of the property that you are animating must
+     return the same type as the starting and ending values that you specify to {@link
+    android.animation.ObjectAnimator}. For example, you must have
+    <code>targetObject.setPropName(float)</code> and
+    <code>targetObject.getPropName(float)</code> if you construct the following {@link
+    android.animation.ObjectAnimator}:
+      <pre>ObjectAnimator.ofFloat(targetObject, "propName", 1f)</pre>
+    </li>
+  </ul>
+
+  <h3 id="type-evaluator">Using the TypeEvaluator</h3>
+
+  <p>If you want to animate a type that is unknown to the Android system,
+  you can create your own evaluator by implementing the {@link
+  android.animation.TypeEvaluator} interface. The types that are known by the Android
+  system are <code>int</code>, <code>float</code>, or a color, which are supported by the
+  {@link android.animation.IntEvaluator}, {@link android.animation.FloatEvaluator}, and
+  {@link android.animation.ArgbEvaluator} type evaluators.</p>
+
+  <p>There is only one method to implement in the {@link android.animation.TypeEvaluator}
+  interface, the {@link android.animation.TypeEvaluator#evaluate evaluate()} method. 
+  This allows the animator that you are using to return an
+  appropriate value for your animated property at the current point of the animation. The
+  {@link android.animation.FloatEvaluator} class demonstrates how to do this:</p>
+  <pre>
+public class FloatEvaluator implements TypeEvaluator {
+
+    public Object evaluate(float fraction, Object startValue, Object endValue) {
+        float startFloat = ((Number) startValue).floatValue();
+        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
+    }
+}
+</pre>
+
+  <p class="note"><strong>Note:</strong> When {@link android.animation.ValueAnimator} (or
+  {@link android.animation.ObjectAnimator}) runs, it calculates a current elapsed
+  fraction of the animation (a value between 0 and 1) and then calculates an eased
+  version of that depending on what interpolator that you are using. The eased fraction
+  is what your {@link android.animation.TypeEvaluator} receives through the <code>fraction</code>
+  parameter, so you do not have to take into account the interpolator
+  when calculating animated values.</p>
+
+  <h3 id="interpolators">Using Interpolators</h3>
+
+  <p>An interpolator define how specific values in an animation are
+  calculated as a function of time. For example, you can specify animations to happen
+  linearly across the whole animation, meaning the animation moves evenly the entire
+  time, or you can specify animations to use non-linear time, for example, using
+  acceleration or deceleration at the beginning or end of the animation.</p>
+  
+  <p>Interpolators in the animation system receive a fraction from Animators that represent the elapsed time
+  of the animation. Interpolators modify this fraction to coincide with the type of
+  animation that it aims to provide. The Android system provides a set of common
+  interpolators in the {@link android.view.animation android.view.animation package}. If
+  none of these suit your needs, you can implement the {@link
+  android.animation.TimeInterpolator} interface and create your own.</p>
+
+  <p>As an example, how the default interpolator {@link
+  android.view.animation.AccelerateDecelerateInterpolator} and the {@link
+  android.view.animation.LinearInterpolator} calculate eased fractions are compared below. The {@link
+  android.view.animation.LinearInterpolator} has no effect on the elapsed fraction,
+  because a linear interpolation is calculated the same way as the elapsed fraction. The
+  {@link android.view.animation.AccelerateDecelerateInterpolator} accelerates into the
+  animation and decelerates out of it. The following methods define the logic for these
+  interpolators:</p>
+
+  <p><strong>AccelerateDecelerateInterpolator</strong></p>
+  <pre>public float getInterpolation(float input) {
+    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
+    }</pre>
+
+  <p><strong>LinearInterpolator</strong></p>
+  <pre>public float getInterpolation(float input) {
+    return input;
+    }</pre>
+
+  <p>The following table represents the approximate values that are calculated by these
+  interpolators for an animation that lasts 1000ms:</p>
+
+  <table>
+    <tr>
+      <th>ms elapsed</th>
+
+      <th>Elapsed fraction/Eased fraction (Linear)</th>
+
+      <th>Eased fraction (Accelerate/Decelerate)</th>
+    </tr>
+
+    <tr>
+      <td>0</td>
+
+      <td>0</td>
+
+      <td>0</td>
+    </tr>
+
+    <tr>
+      <td>200</td>
+
+      <td>.2</td>
+
+      <td>.1</td>
+    </tr>
+
+    <tr>
+      <td>400</td>
+
+      <td>.4</td>
+
+      <td>.345</td>
+    </tr>
+
+    <tr>
+      <td>600</td>
+
+      <td>.6</td>
+
+      <td>.8</td>
+    </tr>
+
+    <tr>
+      <td>800</td>
+
+      <td>.8</td>
+
+      <td>.9</td>
+    </tr>
+
+    <tr>
+      <td>1000</td>
+
+      <td>1</td>
+
+      <td>1</td>
+    </tr>
+  </table>
+
+  <p>As the table shows, the {@link android.view.animation.LinearInterpolator} changes
+  the values at the same speed, .2 for every 200ms that passes. The {@link
+  android.view.animation.AccelerateDecelerateInterpolator} changes the values faster than
+  {@link android.view.animation.LinearInterpolator} between 200ms and 600ms and slower
+  between 600ms and 1000ms.</p>
+
+  <h3 id="keyframes">Specifying Keyframes</h3>
+
+  <p>A {@link android.animation.Keyframe} object consists of a time/value pair that lets
+  you define a specific state at a specific time of an animation. Each keyframe can also
+  have its own interpolator to control the behavior of the animation in the interval
+  between the previous keyframe's time and the time of this keyframe.</p>
+
+  <p>To instantiate a {@link android.animation.Keyframe} object, you must use one of the
+  factory methods, {@link android.animation.Keyframe#ofInt ofInt()}, {@link
+  android.animation.Keyframe#ofFloat ofFloat()}, or {@link
+  android.animation.Keyframe#ofObject ofObject()} to obtain the appropriate type of
+  {@link android.animation.Keyframe}. You then call the {@link
+  android.animation.PropertyValuesHolder#ofKeyframe ofKeyframe()} factory method to
+  obtain a {@link android.animation.PropertyValuesHolder} object. Once you have the
+  object, you can obtain an animator by passing in the {@link
+  android.animation.PropertyValuesHolder} object and the object to animate. The following
+  code snippet demonstrates how to do this:</p>
+  <pre>
+  Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
+  Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
+  Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
+  PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
+  ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
+  rotationAnim.setDuration(5000ms);
+ 
+</pre>For a more complete example on how to use keyframes, see the <a href=
+"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/MultiPropertyAnimation.html">
+  MultiPropertyAnimation</a> sample in APIDemos.
+
+  <h3 id="choreography">Choreographing multiple animations with Animator Sets</h3>
+
+  <p>In many cases, you want to play an animation that depends on when another animation
+  starts or finishes. The Android system lets you bundle animations together into an
+  {@link android.animation.AnimatorSet}, so that you can specify whether to start animations
+  simultaneously, sequentially, or after a specified delay. You can also nest {@link
+  android.animation.AnimatorSet} objects within each other.</p>
+
+  <p>The following sample code taken from the <a href=
+  "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
+  Bouncing Balls</a> sample (modified for simplicity) plays the following
+  {@link android.animation.Animator} objects in the following manner:</p>
+
+  <ol>
+    <li>Plays <code>bounceAnim</code>.</li>
+
+    <li>Plays <code>squashAnim1</code>, <code>squashAnim2</code>,
+    <code>stretchAnim1</code>, and <code>stretchAnim2</code> at the same time.</li>
+
+    <li>Plays <code>bounceBackAnim</code>.</li>
+
+    <li>Plays <code>fadeAnim</code>.</li>
+  </ol>
+  <pre>AnimatorSet bouncer = new AnimatorSet();
+bouncer.play(bounceAnim).before(squashAnim1);
+bouncer.play(squashAnim1).with(squashAnim2);
+bouncer.play(squashAnim1).with(stretchAnim1);
+bouncer.play(squashAnim1).with(stretchAnim2);
+bouncer.play(bounceBackAnim).after(stretchAnim2);
+ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
+fadeAnim.setDuration(250);
+AnimatorSet animatorSet = new AnimatorSet();
+animatorSet.play(bouncer).before(fadeAnim);
+animatorSet.start();
+</pre>
+
+  <p>For a more complete example on how to use animator sets, see the <a href=
+  "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
+  Bouncing Balls</a> sample in APIDemos.</p>
+
+  <h3 id="declaring-xml">Declaring animations in XML</h3>
+
+  <p>As with <a href="view-animation">view animation</a>, you can declare property animations with
+  XML instead of doing it programmatically. The following Android classes also have XML
+  declaration support with the following XML tags:</p>
+
+  <ul>
+    <li>{@link android.animation.ValueAnimator} - <code>&lt;animator&gt;</code></li>
+
+    <li>{@link android.animation.ObjectAnimator} - <code>&lt;objectAnimator&gt;</code></li>
+
+    <li>{@link android.animation.AnimatorSet} - <code>&lt;AnimatorSet&gt;</code></li>
+  </ul>
+
+  <p>Both <code>&lt;animator&gt;</code> ({@link android.animation.ValueAnimator}) and
+  <code>&lt;objectAnimator&gt;</code> ({@link android.animation.ObjectAnimator}) have the
+  following attributes:</p>
+
+  <dl>  
+  <dt><code>android:duration</code></dt>
+  <dd>The number of milliseconds that the animation runs.</dd>
+  
+  <dt><code>android:valueFrom</code> and <code>android:valueTo</code></dt>
+  <dd>The values being animated
+    between. These are restricted to numbers (<code>float</code> or <code>int</code>) in
+    XML. They can be <code>float</code>, <code>int</code>, or any kind of
+    <code>Object</code> when creating animations programmatically.</dd>
+  
+  <dt><code>android:valueType</code></dt>
+  <dd>Set to either <code>"floatType"</code> or <code>"intType"</code>.</dd>
+  
+  <dt><code>android:startDelay</code></dt>
+  <dd>The delay, in milliseconds, before the animation begins
+    playing (after calling {@link android.animation.ValueAnimator#start start()}).</dd>
+  
+  <dt><code>android:repeatCount</code></dt>
+  <dd>How many times to repeat an animation. Set to
+    <code>"-1"</code> for infinite repeating or to a positive integer. For example, a value of
+    <code>"1"</code> means that the animation is repeated once after the initial run of the
+    animation, so the animation plays a total of two times. The default value is
+    <code>"0"</code>.</dd>
+
+  <dt><code>android:repeatMode</code></dt>
+  <dd>How an animation behaves when it reaches the end of the
+    animation. <code>android:repeatCount</code> must be set to a positive integer or
+    <code>"-1"</code> for this attribute to have an effect. Set to <code>"reverse"</code> to
+    have the animation reverse direction with each iteration or <code>"repeat"</code> to
+    have the animation loop from the beginning each time.</dd>
+  </dl>
+  
+  <p>The <code>objectAnimator</code> ({@link android.animation.ObjectAnimator}) element has the
+  additional attribute <code>propertyName</code>, that lets you specify the name of the
+  property being animated. The <code>objectAnimator</code> element does not expose a
+  <code>target</code> attribute, however, so you cannot set the object to animate in the
+  XML declaration. You have to inflate the XML resource by calling
+  {@link android.animation.AnimatorInflater#loadAnimator loadAnimator()} and call
+  {@link android.animation.ObjectAnimator#setTarget setTarget()} to set the target object, before calling
+  {@link android.animation.ObjectAnimator#start start()}.</p>
+
+  <p>The <code>set</code> element ({@link android.animation.AnimatorSet}) exposes a single
+  attribute, <code>ordering</code>. Set this attribute to <code>together</code> (default)
+  to play all the animations in this set at once. Set this attribute to
+  <code>sequentially</code> to play the animations in the order they are declared.</p>
+
+  <p>You can specify nested <code>set</code> tags to further group animations together.
+  The animations that you want to group together should be children of the
+  <code>set</code> tag and can define their own <code>ordering</code> attribute.</p>
+
+  <p>As an example, this XML code creates an {@link android.animation.AnimatorSet} object
+  that animates x and y at the same time (<code>together</code> is the default ordering
+  when nothing is specified), then runs an animation that fades an object out:</p>
+  <pre>&lt;set android:ordering="sequentially"&gt;
+    &lt;set&gt;
+        &lt;objectAnimator
+            android:propertyName="x"
+            android:duration="500"
+            android:valueTo="400"
+            android:valueType="int"/&gt;
+        &lt;objectAnimator
+            android:propertyName="y"
+            android:duration="500"
+            android:valueTo="300"
+            android:valueType="int" &gt;
+        &lt;/set&gt;
+        &lt;objectAnimator
+            android:propertyName="alpha"
+            android:duration="500"
+            android:valueTo="0f"/&gt;
+        &lt;/set&gt;
+</pre>
+
+  <p>In order to run this animation, you must inflate the XML resources in your code to
+  an {@link android.animation.AnimatorSet} object, and then set the target objects for all of
+  the animations before starting the animation set. Calling {@link
+  android.animation.AnimatorSet#setTarget setTarget()} sets a single target object for
+  all children of the {@link android.animation.AnimatorSet}.</p>
+
+  <h2 id="view-animation">View Animation</h2>You can use View Animation in any View
+  object to perform tweened animation and frame by frame animation. Tween animation
+  calculates the animation given information such as the start point, end point, size,
+  rotation, and other common aspects of an animation. Frame by frame animation lets you
+  load a series of Drawable resources one after another to create an animation.
+
+  <h3 id="tween-animation">Tween Animation</h3>
+
+  <p>A tween animation can perform a series of simple transformations (position, size,
+  rotation, and transparency) on the contents of a View object. So, if you have a
+  {@link android.widget.TextView} object, you can move, rotate, grow, or shrink the text. If it has a background
+  image, the background image will be transformed along with the text. The {@link
+  android.view.animation animation package} provides all the classes used in a tween
+  animation.</p>
+
+  <p>A sequence of animation instructions defines the tween animation, defined by either
+  XML or Android code. As with defining a layout, an XML file is recommended because it's
+  more readable, reusable, and swappable than hard-coding the animation. In the example
+  below, we use XML. (To learn more about defining an animation in your application code,
+  instead of XML, refer to the {@link android.view.animation.AnimationSet} class and
+  other {@link android.view.animation.Animation} subclasses.)</p>
+
+  <p>The animation instructions define the transformations that you want to occur, when
+  they will occur, and how long they should take to apply. Transformations can be
+  sequential or simultaneous &mdash; for example, you can have the contents of a TextView
+  move from left to right, and then rotate 180 degrees, or you can have the text move and
+  rotate simultaneously. Each transformation takes a set of parameters specific for that
+  transformation (starting size and ending size for size change, starting angle and
+  ending angle for rotation, and so on), and also a set of common parameters (for
+  instance, start time and duration). To make several transformations happen
+  simultaneously, give them the same start time; to make them sequential, calculate the
+  start time plus the duration of the preceding transformation.</p>
+
+  <p>The animation XML file belongs in the <code>res/anim/</code> directory of your
+  Android project. The file must have a single root element: this will be either a single
+  <code>&lt;alpha&gt;</code>, <code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>,
+  <code>&lt;rotate&gt;</code>, interpolator element, or <code>&lt;set&gt;</code> element
+  that holds groups of these elements (which may include another
+  <code>&lt;set&gt;</code>). By default, all animation instructions are applied
+  simultaneously. To make them occur sequentially, you must specify the
+  <code>startOffset</code> attribute, as shown in the example below.</p>
+
+  <p>The following XML from one of the ApiDemos is used to stretch, then simultaneously
+  spin and rotate a View object.</p>
+  <pre>
+&lt;set android:shareInterpolator="false"&gt;
+   &lt;scale
+          android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+          android:fromXScale="1.0"
+          android:toXScale="1.4"
+          android:fromYScale="1.0"
+          android:toYScale="0.6"
+          android:pivotX="50%"
+          android:pivotY="50%"
+          android:fillAfter="false"
+          android:duration="700" /&gt;
+   &lt;set android:interpolator="@android:anim/decelerate_interpolator"&gt;
+      &lt;scale
+             android:fromXScale="1.4" 
+             android:toXScale="0.0"
+             android:fromYScale="0.6"
+             android:toYScale="0.0" 
+             android:pivotX="50%" 
+             android:pivotY="50%" 
+             android:startOffset="700"
+             android:duration="400" 
+             android:fillBefore="false" /&gt;
+      &lt;rotate 
+             android:fromDegrees="0" 
+             android:toDegrees="-45"
+             android:toYScale="0.0" 
+             android:pivotX="50%" 
+             android:pivotY="50%"
+             android:startOffset="700"
+             android:duration="400" /&gt;
+   &lt;/set&gt;
+&lt;/set&gt;
+</pre>
+
+  <p>Screen coordinates (not used in this example) are (0,0) at the upper left hand
+  corner, and increase as you go down and to the right.</p>
+
+  <p>Some values, such as pivotX, can be specified relative to the object itself or
+  relative to the parent. Be sure to use the proper format for what you want ("50" for
+  50% relative to the parent, or "50%" for 50% relative to itself).</p>
+
+  <p>You can determine how a transformation is applied over time by assigning an {@link
+  android.view.animation.Interpolator}. Android includes several Interpolator subclasses
+  that specify various speed curves: for instance, {@link
+  android.view.animation.AccelerateInterpolator} tells a transformation to start slow and
+  speed up. Each one has an attribute value that can be applied in the XML.</p>
+
+  <p>With this XML saved as <code>hyperspace_jump.xml</code> in the
+  <code>res/anim/</code> directory of the project, the following code will reference
+  it and apply it to an {@link android.widget.ImageView} object from the layout.</p>
+  <pre>
+ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
+Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
+spaceshipImage.startAnimation(hyperspaceJumpAnimation);
+</pre>
+
+  <p>As an alternative to <code>startAnimation()</code>, you can define a starting time
+  for the animation with <code>{@link android.view.animation.Animation#setStartTime(long)
+  Animation.setStartTime()}</code>, then assign the animation to the View with
+  <code>{@link android.view.View#setAnimation(android.view.animation.Animation)
+  View.setAnimation()}</code>.</p>
+
+  <p>For more information on the XML syntax, available tags and attributes, see <a href=
+  "{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
+
+  <p class="note"><strong>Note:</strong> Regardless of how your animation may move or
+  resize, the bounds of the View that holds your animation will not automatically adjust
+  to accommodate it. Even so, the animation will still be drawn beyond the bounds of its
+  View and will not be clipped. However, clipping <em>will occur</em> if the animation
+  exceeds the bounds of the parent View.</p>
+
+  <h3 id="frame-animation">Frame Animation</h3>
+
+  <p>This is a traditional animation in the sense that it is created with a sequence of
+  different images, played in order, like a roll of film. The {@link
+  android.graphics.drawable.AnimationDrawable} class is the basis for frame
+  animations.</p>
+
+  <p>While you can define the frames of an animation in your code, using the {@link
+  android.graphics.drawable.AnimationDrawable} class API, it's more simply accomplished
+  with a single XML file that lists the frames that compose the animation. Like the tween
+  animation above, the XML file for this kind of animation belongs in the
+  <code>res/drawable/</code> directory of your Android project. In this case, the
+  instructions are the order and duration for each frame of the animation.</p>
+
+  <p>The XML file consists of an <code>&lt;animation-list&gt;</code> element as the root
+  node and a series of child <code>&lt;item&gt;</code> nodes that each define a frame: a
+  drawable resource for the frame and the frame duration. Here's an example XML file for
+  a frame-by-frame animation:</p>
+  <pre>
+&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="true"&gt;
+    &lt;item android:drawable="@drawable/rocket_thrust1" android:duration="200" /&gt;
+    &lt;item android:drawable="@drawable/rocket_thrust2" android:duration="200" /&gt;
+    &lt;item android:drawable="@drawable/rocket_thrust3" android:duration="200" /&gt;
+&lt;/animation-list&gt;
+</pre>
+
+  <p>This animation runs for just three frames. By setting the
+  <code>android:oneshot</code> attribute of the list to <var>true</var>, it will cycle
+  just once then stop and hold on the last frame. If it is set <var>false</var> then the
+  animation will loop. With this XML saved as <code>rocket_thrust.xml</code> in the
+  <code>res/drawable/</code> directory of the project, it can be added as the background
+  image to a View and then called to play. Here's an example Activity, in which the
+  animation is added to an {@link android.widget.ImageView} and then animated when the
+  screen is touched:</p>
+  <pre>
+AnimationDrawable rocketAnimation;
+
+public void onCreate(Bundle savedInstanceState) {
+  super.onCreate(savedInstanceState);
+  setContentView(R.layout.main);
+
+  ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
+  rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
+  rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
+}
+
+public boolean onTouchEvent(MotionEvent event) {
+  if (event.getAction() == MotionEvent.ACTION_DOWN) {
+    rocketAnimation.start();
+    return true;
+  }
+  return super.onTouchEvent(event);
+}
+</pre>
+
+  <p>It's important to note that the <code>start()</code> method called on the
+  AnimationDrawable cannot be called during the <code>onCreate()</code> method of your
+  Activity, because the AnimationDrawable is not yet fully attached to the window. If you
+  want to play the animation immediately, without requiring interaction, then you might
+  want to call it from the <code>{@link
+  android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code>
+  method in your Activity, which will get called when Android brings your window into
+  focus.</p>
+
+  <p>For more information on the XML syntax, available tags and attributes, see <a href=
+  "{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
\ No newline at end of file
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index 221406c..11964da 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -343,7 +343,27 @@
 ///////////////////
 /// SAMPLE CODE ///
 ///////////////////
-
+ 
+  {
+    tags: ['sample'],
+    path: 'samples/AccelerometerPlay/index.html',
+    title: {
+      en: 'Accelerometer Play'
+    },
+    description: {
+      en: ''
+    }
+  },
+  {
+    tags: ['sample'],
+    path: 'samples/AccessibilityService/index.html',
+    title: {
+      en: 'Accessibility Service'
+    },
+    description: {
+      en: 'Illustrates an accessibility service that provides custom feedback for the Clock application which comes by default with Android devices'
+    }
+  },
   {
     tags: ['sample', 'layout', 'ui'],
     path: 'samples/ApiDemos/index.html',
@@ -355,7 +375,7 @@
     }
   },
   {
-    tags: ['sample', 'data', 'newfeature', 'accountsync', 'new'],
+    tags: ['sample', 'data', 'newfeature', 'accountsync'],
     path: 'samples/BackupRestore/index.html',
     title: {
       en: 'Backup and Restore'
@@ -395,6 +415,16 @@
     }
   },
   {
+    tags: ['sample', 'ui'],
+    path: 'samples/CubeLiveWallpaper/index.html',
+    title: {
+      en: 'Cube Live Wallpaper'
+    },
+    description: {
+      en: 'An application that demonstrates how to create a live wallpaper and  bundle it in an application that users can install on their devices.'
+    }
+  },
+  {
     tags: ['sample'],
     path: 'samples/Home/index.html',
     title: {
@@ -405,6 +435,16 @@
     }
   },
   {
+    tags: ['sample', 'new'],
+    path: 'samples/Honeycomb-Gallery/index.html',
+    title: {
+      en: 'Honeycomb Gallery'
+    },
+    description: {
+      en: 'An image gallery application using Honeycomb-specific APIs.'
+    }
+  },
+  {
     tags: ['sample', 'gamedev', 'media'],
     path: 'samples/JetBoy/index.html',
     title: {
@@ -415,16 +455,6 @@
     }
   },
   {
-    tags: ['sample', 'ui', 'newfeature'],
-    path: 'samples/CubeLiveWallpaper/index.html',
-    title: {
-      en: 'Live Wallpaper'
-    },
-    description: {
-      en: 'An application that demonstrates how to create a live wallpaper and  bundle it in an application that users can install on their devices.'
-    }
-  },
-  {
     tags: ['sample', 'gamedev', 'media'],
     path: 'samples/LunarLander/index.html',
     title: {
@@ -446,6 +476,16 @@
   },
   {
     tags: ['sample', 'data'],
+    path: 'samples/NFCDemo/index.html',
+    title: {
+      en: 'NFC Demo'
+    },
+    description: {
+      en: 'An application for reading NFC Forum Type 2 Tags using the NFC APIs'
+    }
+  },
+  {
+    tags: ['sample', 'data'],
     path: 'samples/NotePad/index.html',
     title: {
       en: 'Note Pad'
@@ -475,6 +515,16 @@
     }
   },
   {
+    tags: ['sample'],
+    path: 'samples/SipDemo/index.html',
+    title: {
+      en: 'SIP Demo'
+    },
+    description: {
+      en: 'A demo application highlighting how to make internet-based calls with the SIP API.'
+    }
+  },
+  {
     tags: ['sample', 'layout', 'ui'],
     path: 'samples/Snake/index.html',
     title: {
@@ -485,6 +535,16 @@
     }
   },
   {
+    tags: ['sample', 'input'],
+    path: 'samples/SoftKeyboard/index.html',
+    title: {
+      en: 'Soft Keyboard'
+    },
+    description: {
+      en: 'An example of writing an input method for a software keyboard.'
+    }
+  },
+  {
     tags: ['sample', 'testing'],
     path: 'samples/Spinner/index.html',
     title: {
@@ -525,16 +585,6 @@
     }
   },
   {
-    tags: ['sample', 'input'],
-    path: 'samples/SoftKeyboard/index.html',
-    title: {
-      en: 'Soft Keyboard'
-    },
-    description: {
-      en: 'An example of writing an input method for a software keyboard.'
-    }
-  },
-  {
     tags: ['sample', 'ui'],
     path: 'samples/Wiktionary/index.html',
     title: {
@@ -555,7 +605,7 @@
     }
   },
   {
-    tags: ['sample', 'layout', 'new'],
+    tags: ['sample', 'layout'],
     path: 'samples/XmlAdapters/index.html',
     title: {
       en: 'XML Adapters'
diff --git a/docs/html/resources/samples/images/NfcDemo.png b/docs/html/resources/samples/images/NfcDemo.png
new file mode 100644
index 0000000..c175d12
--- /dev/null
+++ b/docs/html/resources/samples/images/NfcDemo.png
Binary files differ
diff --git a/docs/html/resources/samples/images/hcgallery.png b/docs/html/resources/samples/images/hcgallery.png
new file mode 100644
index 0000000..9a80fd7
--- /dev/null
+++ b/docs/html/resources/samples/images/hcgallery.png
Binary files differ
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 27f65bc..30b45f7 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -38,6 +38,15 @@
     AKEY_EVENT_FLAG_START_TRACKING = 0x40000000
 };
 
+enum {
+    /*
+     * Indicates that an input device has switches.
+     * This input source flag is hidden from the API because switches are only used by the system
+     * and applications have no way to interact with them.
+     */
+    AINPUT_SOURCE_SWITCH = 0x80000000,
+};
+
 /*
  * Maximum number of pointers supported per motion event.
  * Smallest number of pointers is 1.
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index ef19579..c650141 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -29,12 +29,8 @@
 public class Credentials {
     private static final String LOGTAG = "Credentials";
 
-    public static final String UNLOCK_ACTION = "android.credentials.UNLOCK";
-
     public static final String INSTALL_ACTION = "android.credentials.INSTALL";
 
-    public static final String SYSTEM_INSTALL_ACTION = "android.credentials.SYSTEM_INSTALL";
-
     /** Key prefix for CA certificates. */
     public static final String CA_CERTIFICATE = "CACERT_";
 
@@ -73,7 +69,7 @@
 
     public void unlock(Context context) {
         try {
-            Intent intent = new Intent(UNLOCK_ACTION);
+            Intent intent = new Intent("com.android.credentials.UNLOCK");
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
             Log.w(LOGTAG, e.toString());
@@ -107,12 +103,4 @@
             Log.w(LOGTAG, e.toString());
         }
     }
-
-    public void installFromSdCard(Context context) {
-        try {
-            context.startActivity(createInstallIntent());
-        } catch (ActivityNotFoundException e) {
-            Log.w(LOGTAG, e.toString());
-        }
-    }
 }
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index c49be93..38e0848 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -23,6 +23,7 @@
 		Program.cpp \
 		ProgramCache.cpp \
 		ResourceCache.cpp \
+		ShapeCache.cpp \
 		SkiaColorFilter.cpp \
 		SkiaShader.cpp \
 		TextureCache.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index fde4f96..bffab95 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -73,6 +73,10 @@
     LOGD("  LayerCache           %8d / %8d", layerCache.getSize(), layerCache.getMaxSize());
     LOGD("  GradientCache        %8d / %8d", gradientCache.getSize(), gradientCache.getMaxSize());
     LOGD("  PathCache            %8d / %8d", pathCache.getSize(), pathCache.getMaxSize());
+    LOGD("  CircleShapeCache     %8d / %8d",
+            circleShapeCache.getSize(), circleShapeCache.getMaxSize());
+    LOGD("  RoundRectShapeCache  %8d / %8d",
+            roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
     LOGD("  TextDropShadowCache  %8d / %8d", dropShadowCache.getSize(),
             dropShadowCache.getMaxSize());
     for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index a11b6bc..c03c347 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -32,6 +32,7 @@
 #include "PatchCache.h"
 #include "ProgramCache.h"
 #include "PathCache.h"
+#include "ShapeCache.h"
 #include "TextDropShadowCache.h"
 #include "FboCache.h"
 #include "ResourceCache.h"
@@ -159,6 +160,8 @@
     GradientCache gradientCache;
     ProgramCache programCache;
     PathCache pathCache;
+    RoundRectShapeCache roundRectShapeCache;
+    CircleShapeCache circleShapeCache;
     PatchCache patchCache;
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 71ec760..014519e 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -45,6 +45,9 @@
 // Turn on to display debug info about paths
 #define DEBUG_PATHS 0
 
+// Turn on to display debug info about shapes
+#define DEBUG_SHAPES 0
+
 // Turn on to display debug info about textures
 #define DEBUG_TEXTURES 0
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index ade85e5..a74a95f 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -103,6 +103,8 @@
     "DrawPatch",
     "DrawColor",
     "DrawRect",
+    "DrawRoundRect",
+    "DrawCircle",
     "DrawPath",
     "DrawLines",
     "DrawText",
@@ -332,6 +334,15 @@
                 renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
             }
             break;
+            case DrawRoundRect: {
+                renderer.drawRoundRect(getFloat(), getFloat(), getFloat(), getFloat(),
+                        getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawCircle: {
+                renderer.drawCircle(getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
             case DrawPath: {
                 renderer.drawPath(getPath(), getPaint());
             }
@@ -601,6 +612,21 @@
     addPaint(paint);
 }
 
+void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, SkPaint* paint) {
+    addOp(DisplayList::DrawRoundRect);
+    addBounds(left, top, right, bottom);
+    addPoint(rx, ry);
+    addPaint(paint);
+}
+
+void DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
+    addOp(DisplayList::DrawCircle);
+    addPoint(x, y);
+    addFloat(radius);
+    addPaint(paint);
+}
+
 void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
     addOp(DisplayList::DrawPath);
     addPath(path);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 05864ec..4b727f6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -110,6 +110,8 @@
         DrawPatch,
         DrawColor,
         DrawRect,
+        DrawRoundRect,
+        DrawCircle,
         DrawPath,
         DrawLines,
         DrawText,
@@ -270,6 +272,9 @@
             float left, float top, float right, float bottom, SkPaint* paint);
     void drawColor(int color, SkXfermode::Mode mode);
     void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
+    void drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, SkPaint* paint);
+    void drawCircle(float x, float y, float radius, SkPaint* paint);
     void drawPath(SkPath* path, SkPaint* paint);
     void drawLines(float* points, int count, SkPaint* paint);
     void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6477eb0..9528dbb 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1305,6 +1305,38 @@
     drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
 }
 
+void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
+        float rx, float ry, SkPaint* paint) {
+    if (mSnapshot->isIgnored()) return;
+
+    glActiveTexture(gTextureUnits[0]);
+
+    const PathTexture* texture = mCaches.roundRectShapeCache.getRoundRect(
+            right - left, bottom - top, rx, ry, paint);
+    if (!texture) return;
+    const AutoTexture autoCleanup(texture);
+
+    const float x = left + texture->left - texture->offset;
+    const float y = top + texture->top - texture->offset;
+
+    drawPathTexture(texture, x, y, paint);
+}
+
+void OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
+    if (mSnapshot->isIgnored()) return;
+
+    glActiveTexture(gTextureUnits[0]);
+
+    const PathTexture* texture = mCaches.circleShapeCache.getCircle(radius, paint);
+    if (!texture) return;
+    const AutoTexture autoCleanup(texture);
+
+    const float left = (x - radius) + texture->left - texture->offset;
+    const float top = (y - radius) + texture->top - texture->offset;
+
+    drawPathTexture(texture, left, top, paint);
+}
+
 void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
     if (quickReject(left, top, right, bottom)) {
         return;
@@ -1453,8 +1485,7 @@
 void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
     if (mSnapshot->isIgnored()) return;
 
-    GLuint textureUnit = 0;
-    glActiveTexture(gTextureUnits[textureUnit]);
+    glActiveTexture(gTextureUnits[0]);
 
     const PathTexture* texture = mCaches.pathCache.get(path, paint);
     if (!texture) return;
@@ -1463,31 +1494,7 @@
     const float x = texture->left - texture->offset;
     const float y = texture->top - texture->offset;
 
-    if (quickReject(x, y, x + texture->width, y + texture->height)) {
-        return;
-    }
-
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    setupDrawAlpha8Color(paint->getColor(), alpha);
-    setupDrawColorFilter();
-    setupDrawShader();
-    setupDrawBlending(true, mode);
-    setupDrawProgram();
-    setupDrawModelView(x, y, x + texture->width, y + texture->height);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms();
-    setupDrawShaderUniforms();
-    setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
-    finishDrawTexture();
+    drawPathTexture(texture, x, y, paint);
 }
 
 void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
@@ -1583,6 +1590,35 @@
 // Drawing implementation
 ///////////////////////////////////////////////////////////////////////////////
 
+void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
+        float x, float y, SkPaint* paint) {
+    if (quickReject(x, y, x + texture->width, y + texture->height)) {
+        return;
+    }
+
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndMode(paint, &alpha, &mode);
+
+    setupDraw();
+    setupDrawWithTexture(true);
+    setupDrawAlpha8Color(paint->getColor(), alpha);
+    setupDrawColorFilter();
+    setupDrawShader();
+    setupDrawBlending(true, mode);
+    setupDrawProgram();
+    setupDrawModelView(x, y, x + texture->width, y + texture->height);
+    setupDrawTexture(texture->id);
+    setupDrawPureColorUniforms();
+    setupDrawColorFilterUniforms();
+    setupDrawShaderUniforms();
+    setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
+
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+
+    finishDrawTexture();
+}
+
 // Same values used by Skia
 #define kStdStrikeThru_Offset   (-6.0f / 21.0f)
 #define kStdUnderline_Offset    (1.0f / 9.0f)
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4150ddc..a43660b 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -107,6 +107,9 @@
             float left, float top, float right, float bottom, SkPaint* paint);
     virtual void drawColor(int color, SkXfermode::Mode mode);
     virtual void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
+    virtual void drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, SkPaint* paint);
+    virtual void drawCircle(float x, float y, float radius, SkPaint* paint);
     virtual void drawPath(SkPath* path, SkPaint* paint);
     virtual void drawLines(float* points, int count, SkPaint* paint);
     virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
@@ -343,6 +346,8 @@
     void drawTextDecorations(const char* text, int bytesCount, float length,
             float x, float y, SkPaint* paint);
 
+    void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
+
     /**
      * Resets the texture coordinates stored in mMeshVertices. Setting the values
      * back to default is achieved by calling:
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 6a0d7ea..2f230b5 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -48,6 +48,7 @@
 #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
 #define PROPERTY_GRADIENT_CACHE_SIZE "ro.hwui.gradient_cache_size"
 #define PROPERTY_PATH_CACHE_SIZE "ro.hwui.path_cache_size"
+#define PROPERTY_SHAPE_CACHE_SIZE "ro.hwui.shape_cache_size"
 #define PROPERTY_DROP_SHADOW_CACHE_SIZE "ro.hwui.drop_shadow_cache_size"
 #define PROPERTY_FBO_CACHE_SIZE "ro.hwui.fbo_cache_size"
 
@@ -66,6 +67,7 @@
 #define DEFAULT_TEXTURE_CACHE_SIZE 20.0f
 #define DEFAULT_LAYER_CACHE_SIZE 8.0f
 #define DEFAULT_PATH_CACHE_SIZE 4.0f
+#define DEFAULT_SHAPE_CACHE_SIZE 1.0f
 #define DEFAULT_PATCH_CACHE_SIZE 512
 #define DEFAULT_GRADIENT_CACHE_SIZE 0.5f
 #define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f
diff --git a/libs/hwui/ShapeCache.cpp b/libs/hwui/ShapeCache.cpp
new file mode 100644
index 0000000..ffa18e3
--- /dev/null
+++ b/libs/hwui/ShapeCache.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "ShapeCache.h"
+
+namespace android {
+namespace uirenderer {
+
+RoundRectShapeCache::RoundRectShapeCache(): ShapeCache<RoundRectShapeCacheEntry>() {
+}
+
+PathTexture* RoundRectShapeCache::getRoundRect(float width, float height,
+        float rx, float ry, SkPaint* paint) {
+    RoundRectShapeCacheEntry entry(width, height, rx, ry, paint);
+    PathTexture* texture = get(entry);
+
+    if (!texture) {
+        SkPath path;
+        SkRect r;
+        r.set(0.0f, 0.0f, width, height);
+        path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
+
+        texture = addTexture(entry, &path, paint);
+    }
+
+    return texture;
+}
+
+CircleShapeCache::CircleShapeCache(): ShapeCache<CircleShapeCacheEntry>() {
+}
+
+PathTexture* CircleShapeCache::getCircle(float radius, SkPaint* paint) {
+    CircleShapeCacheEntry entry(radius, paint);
+    PathTexture* texture = get(entry);
+
+    if (!texture) {
+        SkPath path;
+        path.addCircle(radius, radius, radius, SkPath::kCW_Direction);
+
+        texture = addTexture(entry, &path, paint);
+    }
+
+    return texture;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
new file mode 100644
index 0000000..910d01d
--- /dev/null
+++ b/libs/hwui/ShapeCache.h
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_SHAPE_CACHE_H
+#define ANDROID_HWUI_SHAPE_CACHE_H
+
+#include <GLES2/gl2.h>
+
+#include <SkCanvas.h>
+#include <SkRect.h>
+
+#include "PathCache.h"
+#include "Properties.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Debug
+#if DEBUG_SHAPES
+    #define SHAPE_LOGD(...) LOGD(__VA_ARGS__)
+#else
+    #define SHAPE_LOGD(...)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Describe a shape in the shape cache.
+ */
+struct ShapeCacheEntry {
+    enum ShapeType {
+        kShapeNone,
+        kShapeRoundRect,
+        kShapeCircle,
+        kShapeOval,
+        kShapeArc
+    };
+
+    ShapeCacheEntry() {
+        shapeType = kShapeNone;
+        join = SkPaint::kDefault_Join;
+        cap = SkPaint::kDefault_Cap;
+        style = SkPaint::kFill_Style;
+        miter = 4.0f;
+        strokeWidth = 1.0f;
+    }
+
+    ShapeCacheEntry(const ShapeCacheEntry& entry):
+        shapeType(entry.shapeType), join(entry.join), cap(entry.cap),
+        style(entry.style), miter(entry.miter),
+        strokeWidth(entry.strokeWidth) {
+    }
+
+    ShapeCacheEntry(ShapeType type, SkPaint* paint) {
+        shapeType = type;
+        join = paint->getStrokeJoin();
+        cap = paint->getStrokeCap();
+        float v = paint->getStrokeMiter();
+        miter = *(uint32_t*) &v;
+        v = paint->getStrokeWidth();
+        strokeWidth = *(uint32_t*) &v;
+        style = paint->getStyle();
+    }
+
+    virtual ~ShapeCacheEntry() {
+    }
+
+    // shapeType must be checked in subclasses operator<
+    ShapeType shapeType;
+    SkPaint::Join join;
+    SkPaint::Cap cap;
+    SkPaint::Style style;
+    uint32_t miter;
+    uint32_t strokeWidth;
+
+    bool operator<(const ShapeCacheEntry& rhs) const {
+        LTE_INT(shapeType) {
+            LTE_INT(join) {
+                LTE_INT(cap) {
+                    LTE_INT(style) {
+                        LTE_INT(miter) {
+                            LTE_INT(strokeWidth) {
+                                return lessThan(rhs);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+protected:
+    virtual bool lessThan(const ShapeCacheEntry& rhs) const {
+        return false;
+    }
+}; // struct ShapeCacheEntry
+
+
+struct RoundRectShapeCacheEntry: public ShapeCacheEntry {
+    RoundRectShapeCacheEntry(float width, float height, float rx, float ry, SkPaint* paint):
+            ShapeCacheEntry(ShapeCacheEntry::kShapeRoundRect, paint) {
+        mWidth = *(uint32_t*) &width;
+        mHeight = *(uint32_t*) &height;
+        mRx = *(uint32_t*) &rx;
+        mRy = *(uint32_t*) &ry;
+    }
+
+    RoundRectShapeCacheEntry(): ShapeCacheEntry() {
+        mWidth = 0;
+        mHeight = 0;
+        mRx = 0;
+        mRy = 0;
+    }
+
+    RoundRectShapeCacheEntry(const RoundRectShapeCacheEntry& entry):
+            ShapeCacheEntry(entry) {
+        mWidth = entry.mWidth;
+        mHeight = entry.mHeight;
+        mRx = entry.mRx;
+        mRy = entry.mRy;
+    }
+
+    bool lessThan(const ShapeCacheEntry& r) const {
+        const RoundRectShapeCacheEntry& rhs = (const RoundRectShapeCacheEntry&) r;
+        LTE_INT(mWidth) {
+            LTE_INT(mHeight) {
+                LTE_INT(mRx) {
+                    LTE_INT(mRy) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+private:
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mRx;
+    uint32_t mRy;
+}; // RoundRectShapeCacheEntry
+
+struct CircleShapeCacheEntry: public ShapeCacheEntry {
+    CircleShapeCacheEntry(float radius, SkPaint* paint):
+            ShapeCacheEntry(ShapeCacheEntry::kShapeCircle, paint) {
+        mRadius = *(uint32_t*) &radius;
+    }
+
+    CircleShapeCacheEntry(): ShapeCacheEntry() {
+        mRadius = 0;
+    }
+
+    CircleShapeCacheEntry(const CircleShapeCacheEntry& entry):
+            ShapeCacheEntry(entry) {
+        mRadius = entry.mRadius;
+    }
+
+    bool lessThan(const ShapeCacheEntry& r) const {
+        const CircleShapeCacheEntry& rhs = (const CircleShapeCacheEntry&) r;
+        LTE_INT(mRadius) {
+            return false;
+        }
+        return false;
+    }
+
+private:
+    uint32_t mRadius;
+}; // CircleShapeCacheEntry
+
+/**
+ * A simple LRU shape cache. The cache has a maximum size expressed in bytes.
+ * Any texture added to the cache causing the cache to grow beyond the maximum
+ * allowed size will also cause the oldest texture to be kicked out.
+ */
+template<typename Entry>
+class ShapeCache: public OnEntryRemoved<Entry, PathTexture*> {
+public:
+    ShapeCache();
+    ShapeCache(uint32_t maxByteSize);
+    ~ShapeCache();
+
+    /**
+     * Used as a callback when an entry is removed from the cache.
+     * Do not invoke directly.
+     */
+    void operator()(Entry& path, PathTexture*& texture);
+
+    /**
+     * Clears the cache. This causes all textures to be deleted.
+     */
+    void clear();
+
+    /**
+     * Sets the maximum size of the cache in bytes.
+     */
+    void setMaxSize(uint32_t maxSize);
+    /**
+     * Returns the maximum size of the cache in bytes.
+     */
+    uint32_t getMaxSize();
+    /**
+     * Returns the current size of the cache in bytes.
+     */
+    uint32_t getSize();
+
+protected:
+    PathTexture* addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint);
+
+    PathTexture* get(Entry entry) {
+        return mCache.get(entry);
+    }
+
+private:
+    /**
+     * Generates the texture from a bitmap into the specified texture structure.
+     */
+    void generateTexture(SkBitmap& bitmap, Texture* texture);
+
+    void removeTexture(PathTexture* texture);
+
+    void init();
+
+    GenerationCache<Entry, PathTexture*> mCache;
+    uint32_t mSize;
+    uint32_t mMaxSize;
+    GLuint mMaxTextureSize;
+
+    bool mDebugEnabled;
+}; // class ShapeCache
+
+class RoundRectShapeCache: public ShapeCache<RoundRectShapeCacheEntry> {
+public:
+    RoundRectShapeCache();
+
+    PathTexture* getRoundRect(float width, float height, float rx, float ry, SkPaint* paint);
+}; // class RoundRectShapeCache
+
+class CircleShapeCache: public ShapeCache<CircleShapeCacheEntry> {
+public:
+    CircleShapeCache();
+
+    PathTexture* getCircle(float radius, SkPaint* paint);
+}; // class RoundRectShapeCache
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructors/destructor
+///////////////////////////////////////////////////////////////////////////////
+
+template<class Entry>
+ShapeCache<Entry>::ShapeCache():
+        mCache(GenerationCache<ShapeCacheEntry, PathTexture*>::kUnlimitedCapacity),
+        mSize(0), mMaxSize(MB(DEFAULT_SHAPE_CACHE_SIZE)) {
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_SHAPE_CACHE_SIZE, property, NULL) > 0) {
+        LOGD("  Setting shape cache size to %sMB", property);
+        setMaxSize(MB(atof(property)));
+    } else {
+        LOGD("  Using default shape cache size of %.2fMB", DEFAULT_SHAPE_CACHE_SIZE);
+    }
+    init();
+}
+
+template<class Entry>
+ShapeCache<Entry>::ShapeCache(uint32_t maxByteSize):
+        mCache(GenerationCache<ShapeCacheEntry, PathTexture*>::kUnlimitedCapacity),
+        mSize(0), mMaxSize(maxByteSize) {
+    init();
+}
+
+template<class Entry>
+ShapeCache<Entry>::~ShapeCache() {
+    mCache.clear();
+}
+
+template<class Entry>
+void ShapeCache<Entry>::init() {
+    mCache.setOnEntryRemovedListener(this);
+
+    GLint maxTextureSize;
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+    mMaxTextureSize = maxTextureSize;
+
+    mDebugEnabled = readDebugLevel() & kDebugCaches;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Size management
+///////////////////////////////////////////////////////////////////////////////
+
+template<class Entry>
+uint32_t ShapeCache<Entry>::getSize() {
+    return mSize;
+}
+
+template<class Entry>
+uint32_t ShapeCache<Entry>::getMaxSize() {
+    return mMaxSize;
+}
+
+template<class Entry>
+void ShapeCache<Entry>::setMaxSize(uint32_t maxSize) {
+    mMaxSize = maxSize;
+    while (mSize > mMaxSize) {
+        mCache.removeOldest();
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Callbacks
+///////////////////////////////////////////////////////////////////////////////
+
+template<class Entry>
+void ShapeCache<Entry>::operator()(Entry& path, PathTexture*& texture) {
+    removeTexture(texture);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Caching
+///////////////////////////////////////////////////////////////////////////////
+
+template<class Entry>
+void ShapeCache<Entry>::removeTexture(PathTexture* texture) {
+    if (texture) {
+        const uint32_t size = texture->width * texture->height;
+        mSize -= size;
+
+        SHAPE_LOGD("ShapeCache::callback: delete path: name, size, mSize = %d, %d, %d",
+                texture->id, size, mSize);
+        if (mDebugEnabled) {
+            LOGD("Path deleted, size = %d", size);
+        }
+
+        glDeleteTextures(1, &texture->id);
+        delete texture;
+    }
+}
+
+template<class Entry>
+PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
+        const SkPaint* paint) {
+    const SkRect& bounds = path->getBounds();
+
+    const float pathWidth = fmax(bounds.width(), 1.0f);
+    const float pathHeight = fmax(bounds.height(), 1.0f);
+
+    if (pathWidth > mMaxTextureSize || pathHeight > mMaxTextureSize) {
+        LOGW("Shape too large to be rendered into a texture");
+        return NULL;
+    }
+
+    const float offset = paint->getStrokeWidth() * 1.5f;
+    const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5);
+    const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5);
+
+    const uint32_t size = width * height;
+    // Don't even try to cache a bitmap that's bigger than the cache
+    if (size < mMaxSize) {
+        while (mSize + size > mMaxSize) {
+            mCache.removeOldest();
+        }
+    }
+
+    PathTexture* texture = new PathTexture;
+    texture->left = bounds.fLeft;
+    texture->top = bounds.fTop;
+    texture->offset = offset;
+    texture->width = width;
+    texture->height = height;
+    texture->generation = path->getGenerationID();
+
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kA8_Config, width, height);
+    bitmap.allocPixels();
+    bitmap.eraseColor(0);
+
+    SkPaint pathPaint(*paint);
+
+    // Make sure the paint is opaque, color, alpha, filter, etc.
+    // will be applied later when compositing the alpha8 texture
+    pathPaint.setColor(0xff000000);
+    pathPaint.setAlpha(255);
+    pathPaint.setColorFilter(NULL);
+    pathPaint.setMaskFilter(NULL);
+    pathPaint.setShader(NULL);
+    SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
+    pathPaint.setXfermode(mode)->safeUnref();
+
+    SkCanvas canvas(bitmap);
+    canvas.translate(-bounds.fLeft + offset, -bounds.fTop + offset);
+    canvas.drawPath(*path, pathPaint);
+
+    generateTexture(bitmap, texture);
+
+    if (size < mMaxSize) {
+        mSize += size;
+        SHAPE_LOGD("ShapeCache::get: create path: name, size, mSize = %d, %d, %d",
+                texture->id, size, mSize);
+        if (mDebugEnabled) {
+            LOGD("Shape created, size = %d", size);
+        }
+        mCache.put(entry, texture);
+    } else {
+        texture->cleanup = true;
+    }
+
+    return texture;
+}
+
+template<class Entry>
+void ShapeCache<Entry>::clear() {
+    mCache.clear();
+}
+
+template<class Entry>
+void ShapeCache<Entry>::generateTexture(SkBitmap& bitmap, Texture* texture) {
+    SkAutoLockPixels alp(bitmap);
+    if (!bitmap.readyToDraw()) {
+        LOGE("Cannot generate texture from bitmap");
+        return;
+    }
+
+    glGenTextures(1, &texture->id);
+
+    glBindTexture(GL_TEXTURE_2D, texture->id);
+    // Textures are Alpha8
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+    texture->blend = true;
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
+            GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels());
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_SHAPE_CACHE_H
diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp
index 1663313..f24a71d 100644
--- a/libs/ui/EGLUtils.cpp
+++ b/libs/ui/EGLUtils.cpp
@@ -66,12 +66,6 @@
     if (outConfig == NULL)
         return BAD_VALUE;
     
-    int err;
-    PixelFormatInfo fbFormatInfo;
-    if ((err = getPixelFormatInfo(PixelFormat(format), &fbFormatInfo)) < 0) {
-        return err;
-    }
-
     // Get all the "potential match" configs...
     if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
         return BAD_VALUE;
@@ -81,23 +75,14 @@
         free(configs);
         return BAD_VALUE;
     }
-
-    const int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
-    const int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
-    const int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
-    const int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); 
     
     int i;
     EGLConfig config = NULL;
     for (i=0 ; i<n ; i++) {
-        EGLint r,g,b,a;
-        EGLConfig curr = configs[i];
-        eglGetConfigAttrib(dpy, curr, EGL_RED_SIZE,   &r);
-        eglGetConfigAttrib(dpy, curr, EGL_GREEN_SIZE, &g);
-        eglGetConfigAttrib(dpy, curr, EGL_BLUE_SIZE,  &b);
-        eglGetConfigAttrib(dpy, curr, EGL_ALPHA_SIZE, &a);
-        if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
-            config = curr;
+        EGLint nativeVisualId = 0;
+        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+        if (nativeVisualId>0 && format == nativeVisualId) {
+            config = configs[i];
             break;
         }
     }
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
index 72e2c0b..5a41421 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
@@ -53,7 +53,6 @@
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:layout_gravity="center_vertical"
-                android:paddingTop="5dp"
                 android:layout_marginLeft="8dp"
                 />
         </com.android.systemui.statusbar.tablet.NotificationIconArea>
@@ -63,23 +62,25 @@
         android:id="@+id/notificationTrigger"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
+        android:gravity="center"
         >
         <com.android.systemui.statusbar.tablet.HoloClock
             android:id="@+id/clock"
             android:layout_width="wrap_content"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="4dp"
             >
             <TextView android:id="@+id/time_bg"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:singleLine="true"
-                android:textSize="72dip"
+                android:textSize="40sp"
                 android:textColor="#1f1f1f" />
             <TextView android:id="@+id/time_fg"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:singleLine="true"
-                android:textSize="72dip"
+                android:textSize="40sp"
                 android:textColor="#2e2e2e" />
         </com.android.systemui.statusbar.tablet.HoloClock>
 
@@ -101,14 +102,13 @@
             android:id="@+id/signal_battery_cluster"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
+            android:layout_marginRight="8dp"
             android:orientation="horizontal"
             android:gravity="center"
             >
             <FrameLayout
                 android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
-                android:layout_gravity="top"
-                android:layout_marginTop="19dp"
                 android:layout_marginRight="4dp"
                 >
                 <ImageView
@@ -126,10 +126,6 @@
                 android:id="@+id/battery"
                 android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
-                android:layout_gravity="top"
-                android:layout_marginTop="19dp"
-                android:layout_marginLeft="2dp"
-                android:layout_marginRight="2dp"
                 />
         </LinearLayout>
     </LinearLayout>
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
index 992995c..40f2247 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
@@ -23,7 +23,6 @@
     android:orientation="vertical"
     android:background="@drawable/notify_panel_clock_bg"
     >
-
     <ImageView
         android:id="@+id/network_signal"
         android:layout_height="32dp"
@@ -128,14 +127,14 @@
             android:layout_height="wrap_content"
             android:gravity="right"
             android:singleLine="true"
-            android:textSize="80sp"
+            android:textSize="72sp"
             android:textColor="#999999" />
         <TextView android:id="@+id/time_fg"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="right"
             android:singleLine="true"
-            android:textSize="80sp"
+            android:textSize="72sp"
             android:textColor="#666666" />
     </com.android.systemui.statusbar.tablet.HoloClock>
 
@@ -143,11 +142,17 @@
         android:id="@+id/date"
         style="@style/StatusBarNotificationText"
         android:layout_height="wrap_content"
-        android:layout_width="142dp"
+        android:layout_width="120dp"
         android:layout_alignBottom="@id/clock"
         android:layout_alignParentLeft="true"
         android:gravity="left"
         android:layout_marginLeft="32dp"
         />
 
+    <Button
+        android:id="@+id/mode_toggle"
+        android:background="@null"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
 </RelativeLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 692d41c..973bff9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -47,6 +47,7 @@
 
     boolean mShowing;
     View mTitleArea;
+    View mModeToggle;
     View mSettingsButton;
     View mNotificationButton;
     View mNotificationScroller;
@@ -75,7 +76,8 @@
         mContentParent = (ViewGroup)findViewById(R.id.content_parent);
         mContentParent.bringToFront();
         mTitleArea = findViewById(R.id.title_area);
-        mTitleArea.setOnClickListener(this);
+        mModeToggle = findViewById(R.id.mode_toggle);
+        mModeToggle.setOnClickListener(this);
 
         mScrim = findViewById(R.id.scrim);
         mGlow = findViewById(R.id.glow);
@@ -138,7 +140,7 @@
     }
 
     public void onClick(View v) {
-        if (v == mTitleArea) {
+        if (v == mModeToggle) {
             if (mSettingsView == null) {
                 switchToSettingsMode();
             } else {
@@ -163,10 +165,10 @@
     }
 
     public boolean isInContentArea(int x, int y) {
-        mContentArea.left = mContentFrame.getLeft();
-        mContentArea.top = mTitleArea.getTop();
-        mContentArea.right = mContentFrame.getRight();
-        mContentArea.bottom = mContentFrame.getBottom();
+        mContentArea.left = mContentFrame.getLeft() + mContentFrame.getPaddingLeft();
+        mContentArea.top = mTitleArea.getTop() + mTitleArea.getPaddingTop();
+        mContentArea.right = mContentFrame.getRight() - mContentFrame.getPaddingRight();
+        mContentArea.bottom = mContentFrame.getBottom() - mContentFrame.getPaddingBottom();
         offsetDescendantRectToMyCoords(mContentParent, mContentArea);
         return mContentArea.contains(x, y);
     }
diff --git a/packages/VpnServices/Android.mk b/packages/VpnServices/Android.mk
deleted file mode 100644
index 6cdf674..0000000
--- a/packages/VpnServices/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_JAVA_LIBRARIES :=
-
-LOCAL_PACKAGE_NAME := VpnServices
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
-
-########################
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/VpnServices/AndroidManifest.xml b/packages/VpnServices/AndroidManifest.xml
deleted file mode 100644
index 6092e30..0000000
--- a/packages/VpnServices/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.server.vpn"
-        android:sharedUserId="android.uid.system"
-        >
-    <application android:label="@string/app_label">
-
-        <service android:name=".VpnServiceBinder" android:process=":remote">
-            <intent-filter>
-                <!-- These are the interfaces supported by the service, which
-                     you can bind to. -->
-                <action android:name="android.net.vpn.IVpnService" />
-                <!-- This is an action code you can use to select the service
-                     without explicitly supplying the implementation class. -->
-                <action android:name="android.net.vpn.SERVICE" />
-            </intent-filter>
-        </service>
-
-    </application>
-
-    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
-</manifest>
diff --git a/packages/VpnServices/MODULE_LICENSE_APACHE2 b/packages/VpnServices/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/packages/VpnServices/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/packages/VpnServices/NOTICE b/packages/VpnServices/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/packages/VpnServices/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-2008, The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/packages/VpnServices/res/values-ar/strings.xml b/packages/VpnServices/res/values-ar/strings.xml
deleted file mode 100644
index 6bac120..0000000
--- a/packages/VpnServices/res/values-ar/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"خدمات الشبكة الظاهرية الخاصة (VPN)"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"تم توصيل الشبكة الظاهرية الخاصة (VPN) لـ <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"تم فصل الشبكة الظاهرية الخاصة (VPN) لـ <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"يمكنك اللمس لإعادة الاتصال بالشبكة الظاهرية الخاصة (VPN)."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-bg/strings.xml b/packages/VpnServices/res/values-bg/strings.xml
deleted file mode 100644
index fdcbf64..0000000
--- a/packages/VpnServices/res/values-bg/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN услуги"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Връзката с VPN <xliff:g id="PROFILENAME">%s</xliff:g> бе установена"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Връзката с VPN <xliff:g id="PROFILENAME">%s</xliff:g> бе прекъсната"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Докоснете за повторно свързване с VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-ca/strings.xml b/packages/VpnServices/res/values-ca/strings.xml
deleted file mode 100644
index b37790a..0000000
--- a/packages/VpnServices/res/values-ca/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Serveis VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> connectada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> desconnectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Toqueu-ho per tornar-vos a connectar a una VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-cs/strings.xml b/packages/VpnServices/res/values-cs/strings.xml
deleted file mode 100644
index 96d4cc5..0000000
--- a/packages/VpnServices/res/values-cs/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Služby VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Síť VPN <xliff:g id="PROFILENAME">%s</xliff:g> je připojena"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Síť VPN <xliff:g id="PROFILENAME">%s</xliff:g> odpojena"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotykem se znovu připojíte k síti VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-da/strings.xml b/packages/VpnServices/res/values-da/strings.xml
deleted file mode 100644
index 0f05bbc..0000000
--- a/packages/VpnServices/res/values-da/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-tjenester"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN forbundet"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN afbrudt"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Tryk for at oprette forbindelse til et VPN igen."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-de/strings.xml b/packages/VpnServices/res/values-de/strings.xml
deleted file mode 100644
index b907be8b..0000000
--- a/packages/VpnServices/res/values-de/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-Dienste"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> mit VPN verbunden"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> von VPN getrennt"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Zur Wiederherstellung der Verbindung mit einem VPN berühren"</string>
-</resources>
diff --git a/packages/VpnServices/res/values-el/strings.xml b/packages/VpnServices/res/values-el/strings.xml
deleted file mode 100644
index d96f3e0..0000000
--- a/packages/VpnServices/res/values-el/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Υπηρεσίες VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Το VPN <xliff:g id="PROFILENAME">%s</xliff:g> συνδέθηκε"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Το VPN <xliff:g id="PROFILENAME">%s</xliff:g> αποσυνδέθηκε"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Πατήστε για να επανασυνδεθείτε σε ένα VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-en-rGB/strings.xml b/packages/VpnServices/res/values-en-rGB/strings.xml
deleted file mode 100644
index 905c265..0000000
--- a/packages/VpnServices/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN Services"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN connected"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN disconnected"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Touch to reconnect to a VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-es-rUS/strings.xml b/packages/VpnServices/res/values-es-rUS/strings.xml
deleted file mode 100644
index 8f5053c..0000000
--- a/packages/VpnServices/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Servicios VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN conectados"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN desconectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Tocar para volver a conectarse a una VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-es/strings.xml b/packages/VpnServices/res/values-es/strings.xml
deleted file mode 100644
index 9182459..0000000
--- a/packages/VpnServices/res/values-es/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Servicios VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> conectada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> desconectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Toca para volver a conectarte a una red VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-fa/strings.xml b/packages/VpnServices/res/values-fa/strings.xml
deleted file mode 100644
index 7cee16d..0000000
--- a/packages/VpnServices/res/values-fa/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"سرویس های VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN وصل شد"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN قطع شد"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"برای اتصال مجدد به VPN لمس کنید."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-fi/strings.xml b/packages/VpnServices/res/values-fi/strings.xml
deleted file mode 100644
index b15202a..0000000
--- a/packages/VpnServices/res/values-fi/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-palvelut"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g>: VPN-yhteys muodostettu"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g>: VPN-yhteys katkaistu"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Yhdistä VPN-verkkoon uudelleen koskettamalla."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-fr/strings.xml b/packages/VpnServices/res/values-fr/strings.xml
deleted file mode 100644
index 4a93e0a..0000000
--- a/packages/VpnServices/res/values-fr/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Services VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> connecté"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> déconnecté"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Touchez l\'écran pour vous reconnecter à un VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-hr/strings.xml b/packages/VpnServices/res/values-hr/strings.xml
deleted file mode 100644
index aedb536..0000000
--- a/packages/VpnServices/res/values-hr/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN usluge"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN priključen"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN je isključen"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotaknite za ponovno povezivanje s VPN-om."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-hu/strings.xml b/packages/VpnServices/res/values-hu/strings.xml
deleted file mode 100644
index 44f5427..0000000
--- a/packages/VpnServices/res/values-hu/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-szolgáltatások"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Kapcsolódva a(z) <xliff:g id="PROFILENAME">%s</xliff:g> virtuális magánhálózathoz"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Kapcsolat bontva a(z) <xliff:g id="PROFILENAME">%s</xliff:g> virtuális magánhálózattal"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Érintse meg az újracsatlakozáshoz."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-in/strings.xml b/packages/VpnServices/res/values-in/strings.xml
deleted file mode 100644
index 8b6b4c2..0000000
--- a/packages/VpnServices/res/values-in/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Layanan VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> terhubung"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> terputus"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Sentuh untuk terhubung kembali ke suatu VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-it/strings.xml b/packages/VpnServices/res/values-it/strings.xml
deleted file mode 100644
index 1c7a588..0000000
--- a/packages/VpnServices/res/values-it/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Servizi VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> collegata"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> scollegata"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Tocca per riconnetterti a una rete VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-iw/strings.xml b/packages/VpnServices/res/values-iw/strings.xml
deleted file mode 100644
index 74971d6..0000000
--- a/packages/VpnServices/res/values-iw/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"שירותי VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN של <xliff:g id="PROFILENAME">%s</xliff:g> מחובר"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN של <xliff:g id="PROFILENAME">%s</xliff:g> נותק"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"גע כדי להתחבר שוב ל-VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-ja/strings.xml b/packages/VpnServices/res/values-ja/strings.xml
deleted file mode 100644
index 548d8a9..0000000
--- a/packages/VpnServices/res/values-ja/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPNサービス"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPNが接続されました"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPNが切断されました"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"タップしてVPNに再接続してください。"</string>
-</resources>
diff --git a/packages/VpnServices/res/values-ko/strings.xml b/packages/VpnServices/res/values-ko/strings.xml
deleted file mode 100644
index 4185291..0000000
--- a/packages/VpnServices/res/values-ko/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN 서비스"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 연결됨"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 연결 끊김"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"VPN에 다시 연결하려면 터치하세요."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-lt/strings.xml b/packages/VpnServices/res/values-lt/strings.xml
deleted file mode 100644
index 58f1f58..0000000
--- a/packages/VpnServices/res/values-lt/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPT paslaugos"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPT prijungtas"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPT atjungtas"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Palieskite, kad būtų iš naujo sujungta su VPT."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-lv/strings.xml b/packages/VpnServices/res/values-lv/strings.xml
deleted file mode 100644
index cb80908..0000000
--- a/packages/VpnServices/res/values-lv/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN pakalpojumi"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN ir savienots"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN ir atvienots"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Pieskarieties, lai atkārtoti izveidotu savienojumu ar VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-nb/strings.xml b/packages/VpnServices/res/values-nb/strings.xml
deleted file mode 100644
index 4790600..0000000
--- a/packages/VpnServices/res/values-nb/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-tjenester"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Koblet til VPNet <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Koblet fra VPNet <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Trykk for å koble til et VPN på nytt"</string>
-</resources>
diff --git a/packages/VpnServices/res/values-nl/strings.xml b/packages/VpnServices/res/values-nl/strings.xml
deleted file mode 100644
index 175c7dd..0000000
--- a/packages/VpnServices/res/values-nl/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-services"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> verbonden via VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN-verbinding met <xliff:g id="PROFILENAME">%s</xliff:g> verbroken"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Raak aan om opnieuw verbinding te maken met een VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-pl/strings.xml b/packages/VpnServices/res/values-pl/strings.xml
deleted file mode 100644
index 565d249..0000000
--- a/packages/VpnServices/res/values-pl/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Usługi VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Połączono z siecią VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Rozłączono z siecią VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotknij, aby ponownie połączyć się z siecią VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-pt-rPT/strings.xml b/packages/VpnServices/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 020188f..0000000
--- a/packages/VpnServices/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Serviços VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> ligado"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> desligado"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Toque para voltar a ligar a uma VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-pt/strings.xml b/packages/VpnServices/res/values-pt/strings.xml
deleted file mode 100644
index f47652a..0000000
--- a/packages/VpnServices/res/values-pt/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Serviços de VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN de <xliff:g id="PROFILENAME">%s</xliff:g> conectada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN de <xliff:g id="PROFILENAME">%s</xliff:g> desconectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Toque para reconectar-se a uma VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-rm/strings.xml b/packages/VpnServices/res/values-rm/strings.xml
deleted file mode 100644
index 80f2817..0000000
--- a/packages/VpnServices/res/values-rm/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Servetschs VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> connectà"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> deconnectà"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Tutgar per reconnectar ad in VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-ro/strings.xml b/packages/VpnServices/res/values-ro/strings.xml
deleted file mode 100644
index a22792c..0000000
--- a/packages/VpnServices/res/values-ro/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Servicii VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> conectat"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> deconectat"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Atingeţi pentru a vă reconecta la o reţea VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-ru/strings.xml b/packages/VpnServices/res/values-ru/strings.xml
deleted file mode 100644
index 8a839c3..0000000
--- a/packages/VpnServices/res/values-ru/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Службы VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Сеть VPN (<xliff:g id="PROFILENAME">%s</xliff:g>) подключена"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Сеть VPN (<xliff:g id="PROFILENAME">%s</xliff:g>) отключена"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Нажмите, чтобы повторно подключиться к VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-sk/strings.xml b/packages/VpnServices/res/values-sk/strings.xml
deleted file mode 100644
index 167b6f3..0000000
--- a/packages/VpnServices/res/values-sk/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Služby VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Sieť VPN <xliff:g id="PROFILENAME">%s</xliff:g> je pripojená"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Sieť VPN <xliff:g id="PROFILENAME">%s</xliff:g> odpojená"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotykom sa znova pripojíte k sieti VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-sl/strings.xml b/packages/VpnServices/res/values-sl/strings.xml
deleted file mode 100644
index c5b72c4..0000000
--- a/packages/VpnServices/res/values-sl/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Storitve VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN profila <xliff:g id="PROFILENAME">%s</xliff:g> je povezan"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN profila <xliff:g id="PROFILENAME">%s</xliff:g> je izklopljen"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Dotaknite se, če želite preklopiti v navidezno zasebno omrežje."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-sr/strings.xml b/packages/VpnServices/res/values-sr/strings.xml
deleted file mode 100644
index bfe6cc8..0000000
--- a/packages/VpnServices/res/values-sr/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN услуге"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN веза је успостављена"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN веза је прекинута"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Додирните да бисте се поново повезали са VPN-ом."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-sv/strings.xml b/packages/VpnServices/res/values-sv/strings.xml
deleted file mode 100644
index 24f9f58..0000000
--- a/packages/VpnServices/res/values-sv/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN-tjänster"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN anslutet"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN frånkopplat"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Tryck här om du vill återansluta till ett VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-th/strings.xml b/packages/VpnServices/res/values-th/strings.xml
deleted file mode 100644
index 3aa9c6e..0000000
--- a/packages/VpnServices/res/values-th/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"บริการ VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> เชื่อมต่อ VPN แล้ว"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> ตัดการเชื่อมต่อ VPN แล้ว"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"แตะเพื่อเชื่อมต่อกับ VPN อีกครั้ง"</string>
-</resources>
diff --git a/packages/VpnServices/res/values-tl/strings.xml b/packages/VpnServices/res/values-tl/strings.xml
deleted file mode 100644
index bd988a1..0000000
--- a/packages/VpnServices/res/values-tl/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Mga serbisyo ng VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Hindi konektado ang <xliff:g id="PROFILENAME">%s</xliff:g> VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Hindi konektado ang <xliff:g id="PROFILENAME">%s</xliff:g> VPN"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Galawin upang muling kumonekta sa VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-tr/strings.xml b/packages/VpnServices/res/values-tr/strings.xml
deleted file mode 100644
index 8666b35..0000000
--- a/packages/VpnServices/res/values-tr/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN Hizmetleri"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN bağlandı"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN bağlantısı kesildi"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Bir VPN\'ye tekrar bağlanmak için dokunun."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-uk/strings.xml b/packages/VpnServices/res/values-uk/strings.xml
deleted file mode 100644
index 208659a..0000000
--- a/packages/VpnServices/res/values-uk/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Служби VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> підключ. ч-з VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> роз\'єднано"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Натисн. для повт. з\'єдн. з VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-vi/strings.xml b/packages/VpnServices/res/values-vi/strings.xml
deleted file mode 100644
index 3022c9c..0000000
--- a/packages/VpnServices/res/values-vi/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"Dịch vụ VPN"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Đã kết nối VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Đã ngắt kết nối VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Chạm để kết nối lại với VPN."</string>
-</resources>
diff --git a/packages/VpnServices/res/values-zh-rCN/strings.xml b/packages/VpnServices/res/values-zh-rCN/strings.xml
deleted file mode 100644
index cad08e1..0000000
--- a/packages/VpnServices/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"虚拟专用网服务"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"VPN“<xliff:g id="PROFILENAME">%s</xliff:g>”已连接"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"VPN“<xliff:g id="PROFILENAME">%s</xliff:g>”连接已断开"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"轻触可重新连接到虚拟专用网。"</string>
-</resources>
diff --git a/packages/VpnServices/res/values-zh-rTW/strings.xml b/packages/VpnServices/res/values-zh-rTW/strings.xml
deleted file mode 100644
index ee5a42b..0000000
--- a/packages/VpnServices/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4589592829302498102">"VPN 服務"</string>
-    <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 已連線"</string>
-    <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 已中斷連線"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"輕觸即可重新連線至 VPN。"</string>
-</resources>
diff --git a/packages/VpnServices/res/values/strings.xml b/packages/VpnServices/res/values/strings.xml
deleted file mode 100755
index d82f52a..0000000
--- a/packages/VpnServices/res/values/strings.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Title for the VPN Services activity. -->
-    <string name="app_label">VPN Services</string>
-
-    <string name="vpn_notification_title_connected"><xliff:g id="profilename">%s</xliff:g> VPN connected</string>
-    <string name="vpn_notification_title_disconnected"><xliff:g id="profilename">%s</xliff:g> VPN disconnected</string>
-    <string name="vpn_notification_hint_disconnected">Touch to reconnect to a VPN.</string>
-</resources>
-
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
deleted file mode 100644
index eeafd5a..0000000
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.app.Service;
-import android.content.Intent;
-import android.net.vpn.IVpnService;
-import android.net.vpn.L2tpIpsecProfile;
-import android.net.vpn.L2tpIpsecPskProfile;
-import android.net.vpn.L2tpProfile;
-import android.net.vpn.PptpProfile;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.os.Environment;
-import android.os.IBinder;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-/**
- * The service class for managing a VPN connection. It implements the
- * {@link IVpnService} binder interface.
- */
-public class VpnServiceBinder extends Service {
-    private static final String TAG = VpnServiceBinder.class.getSimpleName();
-    private static final boolean DBG = true;
-
-    private static final String STATES_FILE_RELATIVE_PATH = "/misc/vpn/.states";
-
-    // The actual implementation is delegated to the VpnService class.
-    private VpnService<? extends VpnProfile> mService;
-
-    // TODO(oam): Test VPN when EFS is enabled (will do later)...
-    private static String getStateFilePath() {
-        // This call will return the correcu directory whether Encrypted FS is enabled or not
-        // Disabled: /data/misc/vpn/.states   Enabled: /data/secure/misc/vpn/.states
-	return Environment.getSecureDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH;
-    }
-
-    private final IBinder mBinder = new IVpnService.Stub() {
-        public boolean connect(VpnProfile p, String username, String password) {
-            return VpnServiceBinder.this.connect(p, username, password);
-        }
-
-        public void disconnect() {
-            VpnServiceBinder.this.disconnect();
-        }
-
-        public void checkStatus(VpnProfile p) {
-            VpnServiceBinder.this.checkStatus(p);
-        }
-    };
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        checkSavedStates();
-    }
-
-
-    @Override
-    public void onStart(Intent intent, int startId) {
-        super.onStart(intent, startId);
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    void saveStates() throws IOException {
-        if (DBG) Log.d("VpnServiceBinder", "     saving states");
-        ObjectOutputStream oos =
-                new ObjectOutputStream(new FileOutputStream(getStateFilePath()));
-        oos.writeObject(mService);
-        oos.close();
-    }
-
-    void removeStates() {
-        try {
-            File f = new File(getStateFilePath());
-            if (f.exists()) f.delete();
-        } catch (Throwable e) {
-            if (DBG) Log.d("VpnServiceBinder", "     remove states: " + e);
-        }
-    }
-
-    private synchronized boolean connect(final VpnProfile p,
-            final String username, final String password) {
-        if (mService != null) return false;
-        final VpnService s = mService = createService(p);
-
-        new Thread(new Runnable() {
-            public void run() {
-                s.onConnect(username, password);
-            }
-        }).start();
-        return true;
-    }
-
-    private synchronized void disconnect() {
-        if (mService == null) return;
-        final VpnService s = mService;
-
-        new Thread(new Runnable() {
-            public void run() {
-                s.onDisconnect();
-            }
-        }).start();
-    }
-
-    private synchronized void checkStatus(VpnProfile p) {
-        if ((mService == null)
-                || (!p.getName().equals(mService.mProfile.getName()))) {
-            broadcastConnectivity(p.getName(), VpnState.IDLE);
-        } else {
-            broadcastConnectivity(p.getName(), mService.getState());
-        }
-    }
-
-    private void checkSavedStates() {
-        try {
-            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
-                    getStateFilePath()));
-            mService = (VpnService<? extends VpnProfile>) ois.readObject();
-            mService.recover(this);
-            ois.close();
-        } catch (FileNotFoundException e) {
-            // do nothing
-        } catch (Throwable e) {
-            Log.i("VpnServiceBinder", "recovery error, remove states: " + e);
-            removeStates();
-        }
-    }
-
-    private VpnService<? extends VpnProfile> createService(VpnProfile p) {
-        switch (p.getType()) {
-            case L2TP:
-                L2tpService l2tp = new L2tpService();
-                l2tp.setContext(this, (L2tpProfile) p);
-                return l2tp;
-
-            case PPTP:
-                PptpService pptp = new PptpService();
-                pptp.setContext(this, (PptpProfile) p);
-                return pptp;
-
-            case L2TP_IPSEC_PSK:
-                L2tpIpsecPskService psk = new L2tpIpsecPskService();
-                psk.setContext(this, (L2tpIpsecPskProfile) p);
-                return psk;
-
-            case L2TP_IPSEC:
-                L2tpIpsecService l2tpIpsec = new L2tpIpsecService();
-                l2tpIpsec.setContext(this, (L2tpIpsecProfile) p);
-                return l2tpIpsec;
-
-            default:
-                return null;
-        }
-    }
-
-    private void broadcastConnectivity(String name, VpnState s) {
-        new VpnManager(this).broadcastConnectivity(name, s);
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index eb4d930..5b80a93 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -100,17 +100,27 @@
                 || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
                 || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
 
+        // TODO: re-enable on phones with keyboards
+        final boolean isPhysicalKbShowing = false;
         mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
         mKeyboardViewAlpha = (PasswordEntryKeyboardView) findViewById(R.id.keyboardAlpha);
         mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
         mPasswordEntry.setOnEditorActionListener(this);
+        mPasswordEntry.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                if (mIsAlpha && !isPhysicalKbShowing) {
+                    mKeyboardViewAlpha.setVisibility(
+                            mKeyboardViewAlpha.getVisibility() == View.VISIBLE
+                            ? View.GONE : View.VISIBLE);
+                    mCallback.pokeWakelock();
+                }
+            }
+        });
         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
         mEmergencyCallButton.setOnClickListener(this);
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
 
         mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
-        // TODO: re-enable on phones with keyboards
-        boolean isPhysicalKbShowing = false;
         //mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
         if (mKeyboardViewAlpha == null || !mIsAlpha) {
             mKeyboardHelper.setKeyboardMode(mIsAlpha ?
@@ -123,24 +133,21 @@
             mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
             mKeyboardHelperAlpha.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
             mKeyboardView.setVisibility(View.GONE);
-            mKeyboardViewAlpha.setVisibility(isPhysicalKbShowing ? View.INVISIBLE : View.VISIBLE);
             mPasswordEntry.setWidth(mKeyboardViewAlpha.getLayoutParams().width);
         }
 
-        mPasswordEntry.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0,
-                0, 0);
         mPasswordEntry.requestFocus();
 
         // This allows keyboards with overlapping qwerty/numeric keys to choose just the
         // numeric keys.
         if (mIsAlpha) {
             mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
-            mStatusView.setHelpMessage(R.string.keyguard_password_enter_password_code,
-                    StatusView.LOCK_ICON);
+            // mStatusView.setHelpMessage(R.string.keyguard_password_enter_password_code,
+            //      StatusView.LOCK_ICON);
         } else {
             mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
-            mStatusView.setHelpMessage(R.string.keyguard_password_enter_pin_code,
-                    StatusView.LOCK_ICON);
+            //mStatusView.setHelpMessage(R.string.keyguard_password_enter_pin_code,
+            //      StatusView.LOCK_ICON);
         }
 
         mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ?
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 8e9a5a4..2e83256 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -744,7 +744,7 @@
 }
 
 uint32_t SwitchInputMapper::getSources() {
-    return 0;
+    return AINPUT_SOURCE_SWITCH;
 }
 
 void SwitchInputMapper::process(const RawEvent* rawEvent) {
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 775747c..98d627d 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -1484,7 +1484,7 @@
     SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
     addMapperAndConfigure(mapper);
 
-    ASSERT_EQ(uint32_t(0), mapper->getSources());
+    ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper->getSources());
 }
 
 TEST_F(SwitchInputMapperTest, GetSwitchState) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 2321e30..bd3c554 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -32,6 +32,7 @@
 import android.net.NetworkUtils;
 import android.net.Proxy;
 import android.net.ProxyProperties;
+import android.net.vpn.VpnManager;
 import android.net.wifi.WifiStateTracker;
 import android.os.Binder;
 import android.os.Handler;
@@ -442,6 +443,8 @@
         mSettingsObserver.observe(mContext);
 
         loadGlobalProxy();
+
+        VpnManager.startVpnService(context);
     }
 
 
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 418e7f8..3abfc12 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -34,9 +34,9 @@
 
 RotationVectorSensor::RotationVectorSensor(sensor_t const* list, size_t count)
     : mSensorDevice(SensorDevice::getInstance()),
-      mALowPass(M_SQRT1_2, 5.0f),
+      mALowPass(M_SQRT1_2, 1.5f),
       mAX(mALowPass), mAY(mALowPass), mAZ(mALowPass),
-      mMLowPass(M_SQRT1_2, 2.5f),
+      mMLowPass(M_SQRT1_2, 1.5f),
       mMX(mMLowPass), mMY(mMLowPass), mMZ(mMLowPass)
 {
     for (size_t i=0 ; i<count ; i++) {
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index b7c9512..17699f8 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -38,9 +38,9 @@
     double mAccTime;
     double mMagTime;
     SecondOrderLowPassFilter mALowPass;
-    BiquadFilter mAX, mAY, mAZ;
+    CascadedBiquadFilter mAX, mAY, mAZ;
     SecondOrderLowPassFilter mMLowPass;
-    BiquadFilter mMX, mMY, mMZ;
+    CascadedBiquadFilter mMX, mMY, mMZ;
 
 public:
     RotationVectorSensor(sensor_t const* list, size_t count);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index b2d2a98..39a4614 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -122,6 +122,8 @@
         ignoreResultList.add("storage/indexeddb"); // indexeddb not supported
         ignoreResultList.add("storage/private-browsing-readonly.html"); // private browsing not supported
         ignoreResultList.add("websocket/tests/workers"); // workers not supported
+        ignoreResultList.add("dom/xhtml/level2/html/htmldocument04.xhtml"); // /mnt/sdcard on SR uses lowercase filesystem, this test checks filename and is case senstive.
+        ignoreResultList.add("dom/html/level2/html/htmldocument04.html"); // ditto
 
         // Expected failures due to missing expected results
         ignoreResultList.add("dom/xhtml/level3/core/canonicalform08.xhtml");
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index a3466e2..9c4fa97 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -37,6 +37,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.webkit.ConsoleMessage;
+import android.webkit.CookieManager;
 import android.webkit.GeolocationPermissions;
 import android.webkit.HttpAuthHandler;
 import android.webkit.JsPromptResult;
@@ -827,6 +828,7 @@
         setDefaultWebSettings(mWebView);
         mIsGeolocationPermissionSet = false;
         mPendingGeolocationPermissionCallbacks = null;
+        CookieManager.getInstance().removeAllCookie();
     }
 
     private long[] getDrawWebViewTime(WebView view, int count) {
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 7a61b3c..1d67964 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -25,6 +25,15 @@
         android:hardwareAccelerated="true">
 
         <activity
+                android:name="ShapesActivity"
+                android:label="_Shapes">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="SimplePatchActivity"
                 android:label="_SimplePatch"
                 android:theme="@android:style/Theme.Translucent.NoTitleBar">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java
new file mode 100644
index 0000000..536a669
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ShapesActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(new ShapesView(this));
+    }
+
+    static class ShapesView extends View {
+        private Paint mNormalPaint;
+        private Paint mStrokePaint;
+        private Paint mFillPaint;
+        private RectF mRect;
+
+        ShapesView(Context c) {
+            super(c);
+
+            mRect = new RectF(0.0f, 0.0f, 160.0f, 90.0f);
+
+            mNormalPaint = new Paint();
+            mNormalPaint.setAntiAlias(true);
+            mNormalPaint.setColor(0xff0000ff);
+            mNormalPaint.setStrokeWidth(6.0f);
+            mNormalPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+            mStrokePaint = new Paint();
+            mStrokePaint.setAntiAlias(true);
+            mStrokePaint.setColor(0xff0000ff);
+            mStrokePaint.setStrokeWidth(6.0f);
+            mStrokePaint.setStyle(Paint.Style.STROKE);
+            
+            mFillPaint = new Paint();
+            mFillPaint.setAntiAlias(true);
+            mFillPaint.setColor(0xff0000ff);
+            mFillPaint.setStyle(Paint.Style.FILL);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            canvas.save();
+            canvas.translate(50.0f, 50.0f);
+            canvas.drawRoundRect(mRect, 6.0f, 6.0f, mNormalPaint);
+
+            canvas.translate(0.0f, 110.0f);
+            canvas.drawRoundRect(mRect, 6.0f, 6.0f, mStrokePaint);
+
+            canvas.translate(0.0f, 110.0f);
+            canvas.drawRoundRect(mRect, 6.0f, 6.0f, mFillPaint);
+            canvas.restore();
+
+            canvas.save();
+            canvas.translate(250.0f, 50.0f);
+            canvas.drawCircle(80.0f, 45.0f, 45.0f, mNormalPaint);
+
+            canvas.translate(0.0f, 110.0f);
+            canvas.drawCircle(80.0f, 45.0f, 45.0f, mStrokePaint);
+
+            canvas.translate(0.0f, 110.0f);
+            canvas.drawCircle(80.0f, 45.0f, 45.0f, mFillPaint);
+            canvas.restore();
+        }
+    }
+}
diff --git a/vpn/java/android/net/vpn/IVpnService.aidl b/vpn/java/android/net/vpn/IVpnService.aidl
index fedccb0..6bf3edd 100644
--- a/vpn/java/android/net/vpn/IVpnService.aidl
+++ b/vpn/java/android/net/vpn/IVpnService.aidl
@@ -24,10 +24,11 @@
  */
 interface IVpnService {
     /**
-     * Sets up the VPN connection.
+     * Sets up a VPN connection.
      * @param profile the profile object
      * @param username the username for authentication
      * @param password the corresponding password for authentication
+     * @return true if VPN is successfully connected
      */
     boolean connect(in VpnProfile profile, String username, String password);
 
@@ -37,7 +38,13 @@
     void disconnect();
 
     /**
-     * Makes the service broadcast the connectivity state.
+     * Gets the the current connection state.
      */
-    void checkStatus(in VpnProfile profile);
+    String getState(in VpnProfile profile);
+
+    /**
+     * Returns the idle state.
+     * @return true if the system is not connecting/connected to a VPN
+     */
+    boolean isIdle();
 }
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index ce40b5d..02486bb 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -16,17 +16,19 @@
 
 package android.net.vpn;
 
-import java.io.File;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.os.Environment;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.util.Log;
 
+import com.android.server.vpn.VpnServiceBinder;
+
 /**
  * The class provides interface to manage all VPN-related tasks, including:
  * <ul>
@@ -40,8 +42,6 @@
  * {@hide}
  */
 public class VpnManager {
-    // Action for broadcasting a connectivity state.
-    private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
     /** Key to the profile name of a connectivity broadcast event. */
     public static final String BROADCAST_PROFILE_NAME = "profile_name";
     /** Key to the connectivity state of a connectivity broadcast event. */
@@ -74,8 +74,10 @@
     private static final String PACKAGE_PREFIX =
             VpnManager.class.getPackage().getName() + ".";
 
-    // Action to start VPN service
-    private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE";
+    // Action for broadcasting a connectivity state.
+    private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
+
+    private static final String VPN_SERVICE_NAME = "vpn";
 
     // Action to start VPN settings
     private static final String ACTION_VPN_SETTINGS =
@@ -96,13 +98,76 @@
         return VpnType.values();
     }
 
+    public static void startVpnService(Context c) {
+        ServiceManager.addService(VPN_SERVICE_NAME, new VpnServiceBinder(c));
+    }
+
     private Context mContext;
+    private IVpnService mVpnService;
 
     /**
      * Creates a manager object with the specified context.
      */
     public VpnManager(Context c) {
         mContext = c;
+        createVpnServiceClient();
+    }
+
+    private void createVpnServiceClient() {
+        IBinder b = ServiceManager.getService(VPN_SERVICE_NAME);
+        mVpnService = IVpnService.Stub.asInterface(b);
+    }
+
+    /**
+     * Sets up a VPN connection.
+     * @param profile the profile object
+     * @param username the username for authentication
+     * @param password the corresponding password for authentication
+     * @return true if VPN is successfully connected
+     */
+    public boolean connect(VpnProfile p, String username, String password) {
+        try {
+            return mVpnService.connect(p, username, password);
+        } catch (RemoteException e) {
+            Log.e(TAG, "connect()", e);
+            return false;
+        }
+    }
+
+    /**
+     * Tears down the VPN connection.
+     */
+    public void disconnect() {
+        try {
+            mVpnService.disconnect();
+        } catch (RemoteException e) {
+            Log.e(TAG, "disconnect()", e);
+        }
+    }
+
+    /**
+     * Gets the the current connection state.
+     */
+    public VpnState getState(VpnProfile p) {
+        try {
+            return Enum.valueOf(VpnState.class, mVpnService.getState(p));
+        } catch (RemoteException e) {
+            Log.e(TAG, "getState()", e);
+            return VpnState.IDLE;
+        }
+    }
+
+    /**
+     * Returns the idle state.
+     * @return true if the system is not connecting/connected to a VPN
+     */
+    public boolean isIdle() {
+        try {
+            return mVpnService.isIdle();
+        } catch (RemoteException e) {
+            Log.e(TAG, "isIdle()", e);
+            return true;
+        }
     }
 
     /**
@@ -134,33 +199,6 @@
         }
     }
 
-    /**
-     * Starts the VPN service to establish VPN connection.
-     */
-    public void startVpnService() {
-        mContext.startService(new Intent(ACTION_VPN_SERVICE));
-    }
-
-    /**
-     * Stops the VPN service.
-     */
-    public void stopVpnService() {
-        mContext.stopService(new Intent(ACTION_VPN_SERVICE));
-    }
-
-    /**
-     * Binds the specified ServiceConnection with the VPN service.
-     */
-    public boolean bindVpnService(ServiceConnection c) {
-        if (!mContext.bindService(new Intent(ACTION_VPN_SERVICE), c, 0)) {
-            Log.w(TAG, "failed to connect to VPN service");
-            return false;
-        } else {
-            Log.d(TAG, "succeeded to connect to VPN service");
-            return true;
-        }
-    }
-
     /** Broadcasts the connectivity state of the specified profile. */
     public void broadcastConnectivity(String profileName, VpnState s) {
         broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR);
diff --git a/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java b/vpn/java/com/android/server/vpn/DaemonProxy.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
rename to vpn/java/com/android/server/vpn/DaemonProxy.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
rename to vpn/java/com/android/server/vpn/L2tpIpsecPskService.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/vpn/java/com/android/server/vpn/L2tpIpsecService.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
rename to vpn/java/com/android/server/vpn/L2tpIpsecService.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java b/vpn/java/com/android/server/vpn/L2tpService.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/L2tpService.java
rename to vpn/java/com/android/server/vpn/L2tpService.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/PptpService.java b/vpn/java/com/android/server/vpn/PptpService.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/PptpService.java
rename to vpn/java/com/android/server/vpn/PptpService.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnConnectingError.java b/vpn/java/com/android/server/vpn/VpnConnectingError.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/VpnConnectingError.java
rename to vpn/java/com/android/server/vpn/VpnConnectingError.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java b/vpn/java/com/android/server/vpn/VpnDaemons.java
similarity index 100%
rename from packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java
rename to vpn/java/com/android/server/vpn/VpnDaemons.java
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/vpn/java/com/android/server/vpn/VpnService.java
similarity index 94%
rename from packages/VpnServices/src/com/android/server/vpn/VpnService.java
rename to vpn/java/com/android/server/vpn/VpnService.java
index a618423..4966c06 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/vpn/java/com/android/server/vpn/VpnService.java
@@ -27,8 +27,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.R;
+
 import java.io.IOException;
-import java.io.Serializable;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
@@ -37,8 +38,7 @@
 /**
  * The service base class for managing a type of VPN connection.
  */
-abstract class VpnService<E extends VpnProfile> implements Serializable {
-    static final long serialVersionUID = 1L;
+abstract class VpnService<E extends VpnProfile> {
     private static final boolean DBG = true;
     private static final int NOTIFICATION_ID = 1;
 
@@ -55,10 +55,8 @@
 
     private final String TAG = VpnService.class.getSimpleName();
 
-    // FIXME: profile is only needed in connecting phase, so we can just save
-    // the profile name and service class name for recovery
     E mProfile;
-    transient VpnServiceBinder mContext;
+    transient Context mContext;
 
     private VpnState mState = VpnState.IDLE;
     private Throwable mError;
@@ -105,12 +103,8 @@
         return InetAddress.getByName(hostName).getHostAddress();
     }
 
-    void setContext(VpnServiceBinder context, E profile) {
+    void setContext(Context context, E profile) {
         mProfile = profile;
-        recover(context);
-    }
-
-    void recover(VpnServiceBinder context) {
         mContext = context;
         mNotification = new NotificationHelper();
 
@@ -124,6 +118,10 @@
         return mState;
     }
 
+    boolean isIdle() {
+      return (mState == VpnState.IDLE);
+    }
+
     synchronized boolean onConnect(String username, String password) {
         try {
             setState(VpnState.CONNECTING);
@@ -216,21 +214,12 @@
 
         mStartTime = System.currentTimeMillis();
 
-        // Correct order to make sure VpnService doesn't break when killed:
-        // (1) set state to CONNECTED
-        // (2) save states
-        // (3) set DNS
         setState(VpnState.CONNECTED);
-        saveSelf();
         setVpnDns();
 
         startConnectivityMonitor();
     }
 
-    private void saveSelf() throws IOException {
-        mContext.saveStates();
-    }
-
     private synchronized void onFinalCleanUp() {
         if (DBG) Log.d(TAG, "onFinalCleanUp()");
 
@@ -243,10 +232,7 @@
         restoreOriginalDomainSuffices();
         setState(VpnState.IDLE);
 
-        // stop the service itself
         SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
-        mContext.removeStates();
-        mContext.stopSelf();
     }
 
     private boolean anyError() {
@@ -413,9 +399,6 @@
         }
     }
 
-    private class DaemonHelper implements Serializable {
-    }
-
     // Helper class for showing, updating notification.
     private class NotificationHelper {
         private NotificationManager mNotificationManager = (NotificationManager)
diff --git a/vpn/java/com/android/server/vpn/VpnServiceBinder.java b/vpn/java/com/android/server/vpn/VpnServiceBinder.java
new file mode 100644
index 0000000..c474ff9
--- /dev/null
+++ b/vpn/java/com/android/server/vpn/VpnServiceBinder.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vpn;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.net.vpn.IVpnService;
+import android.net.vpn.L2tpIpsecProfile;
+import android.net.vpn.L2tpIpsecPskProfile;
+import android.net.vpn.L2tpProfile;
+import android.net.vpn.PptpProfile;
+import android.net.vpn.VpnManager;
+import android.net.vpn.VpnProfile;
+import android.net.vpn.VpnState;
+import android.util.Log;
+
+/**
+ * The service class for managing a VPN connection. It implements the
+ * {@link IVpnService} binder interface.
+ */
+public class VpnServiceBinder extends IVpnService.Stub {
+    private static final String TAG = VpnServiceBinder.class.getSimpleName();
+    private static final boolean DBG = true;
+
+    // The actual implementation is delegated to the VpnService class.
+    private VpnService<? extends VpnProfile> mService;
+
+    private Context mContext;
+
+    public VpnServiceBinder(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public synchronized boolean connect(VpnProfile p, final String username,
+            final String password) {
+        if ((mService != null) && !mService.isIdle()) return false;
+        final VpnService s = mService = createService(p);
+
+        new Thread(new Runnable() {
+            public void run() {
+                s.onConnect(username, password);
+            }
+        }).start();
+        return true;
+    }
+
+    @Override
+    public synchronized void disconnect() {
+        if (mService == null) return;
+        final VpnService s = mService;
+        mService = null;
+
+        new Thread(new Runnable() {
+            public void run() {
+                s.onDisconnect();
+            }
+        }).start();
+    }
+
+    @Override
+    public synchronized String getState(VpnProfile p) {
+        if ((mService == null)
+                || (!p.getName().equals(mService.mProfile.getName()))) {
+            return VpnState.IDLE.toString();
+        } else {
+            return mService.getState().toString();
+        }
+    }
+
+    @Override
+    public synchronized boolean isIdle() {
+        return (mService == null || mService.isIdle());
+    }
+
+    private VpnService<? extends VpnProfile> createService(VpnProfile p) {
+        switch (p.getType()) {
+            case L2TP:
+                L2tpService l2tp = new L2tpService();
+                l2tp.setContext(mContext, (L2tpProfile) p);
+                return l2tp;
+
+            case PPTP:
+                PptpService pptp = new PptpService();
+                pptp.setContext(mContext, (PptpProfile) p);
+                return pptp;
+
+            case L2TP_IPSEC_PSK:
+                L2tpIpsecPskService psk = new L2tpIpsecPskService();
+                psk.setContext(mContext, (L2tpIpsecPskProfile) p);
+                return psk;
+
+            case L2TP_IPSEC:
+                L2tpIpsecService l2tpIpsec = new L2tpIpsecService();
+                l2tpIpsec.setContext(mContext, (L2tpIpsecProfile) p);
+                return l2tpIpsec;
+
+            default:
+                return null;
+        }
+    }
+}