Merge "Invisible views can't start animations"
diff --git a/api/current.txt b/api/current.txt
index 1d5692f..51c9348 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5810,6 +5810,7 @@
     method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
     field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
     field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
+    field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
     field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
     field public static final int DONT_KILL_APP = 1; // 0x1
     field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index b0e4a86..e433079 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -120,6 +120,11 @@
             return;
         }
 
+        if ("disable-user".equals(op)) {
+            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
+            return;
+        }
+
         if ("setInstallLocation".equals(op)) {
             runSetInstallLocation();
             return;
@@ -970,6 +975,8 @@
                 return "enabled";
             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
                 return "disabled";
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
+                return "disabled-user";
         }
         return "unknown";
     }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index c0a1d8e..454cb31 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -417,6 +417,12 @@
     public boolean enabled = true;
 
     /**
+     * For convenient access to the current enabled setting of this app.
+     * @hide
+     */
+    public int enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+
+    /**
      * For convenient access to package's install location.
      * @hide
      */
@@ -508,6 +514,7 @@
         uid = orig.uid;
         targetSdkVersion = orig.targetSdkVersion;
         enabled = orig.enabled;
+        enabledSetting = orig.enabledSetting;
         installLocation = orig.installLocation;
         manageSpaceActivityName = orig.manageSpaceActivityName;
         descriptionRes = orig.descriptionRes;
@@ -544,6 +551,7 @@
         dest.writeInt(uid);
         dest.writeInt(targetSdkVersion);
         dest.writeInt(enabled ? 1 : 0);
+        dest.writeInt(enabledSetting);
         dest.writeInt(installLocation);
         dest.writeString(manageSpaceActivityName);
         dest.writeString(backupAgentName);
@@ -581,6 +589,7 @@
         uid = source.readInt();
         targetSdkVersion = source.readInt();
         enabled = source.readInt() != 0;
+        enabledSetting = source.readInt();
         installLocation = source.readInt();
         manageSpaceActivityName = source.readString();
         backupAgentName = source.readString();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1cd8ec0..dd684cd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -224,11 +224,41 @@
      */
     public static final int SIGNATURE_UNKNOWN_PACKAGE = -4;
 
+    /**
+     * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
+     * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
+     * component or application is in its default enabled state (as specified
+     * in its manifest).
+     */
     public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0;
+
+    /**
+     * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
+     * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
+     * component or application has been explictily enabled, regardless of
+     * what it has specified in its manifest.
+     */
     public static final int COMPONENT_ENABLED_STATE_ENABLED = 1;
+
+    /**
+     * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
+     * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
+     * component or application has been explicitly disabled, regardless of
+     * what it has specified in its manifest.
+     */
     public static final int COMPONENT_ENABLED_STATE_DISABLED = 2;
 
     /**
+     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: The
+     * user has explicitly disabled the application, regardless of what it has
+     * specified in its manifest.  Because this is due to the user's request,
+     * they may re-enable it if desired through the appropriate system UI.  This
+     * option currently <strong>can not</strong> be used with
+     * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
+     */
+    public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
+
+    /**
      * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
      * indicate that this package should be installed as forward locked, i.e. only the app itself
      * should have access to its code and non-resource assets.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 31ad6e9..e927f6c 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3128,9 +3128,11 @@
         }
         if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
-        } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+        } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                || p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
             ai.enabled = false;
         }
+        ai.enabledSetting = p.mSetEnabled;
         return ai;
     }
 
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 17b1031..4368e31 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -476,7 +476,96 @@
      }
 
     /**
-     * Fields and helpers for interacting with Calendars.
+     * Constants and helpers for the Calendars table, which contains details for
+     * individual calendars. <h3>Operations</h3> All operations can be done
+     * either as an app or as a sync adapter. To perform an operation as a sync
+     * adapter {@link #CALLER_IS_SYNCADAPTER} should be set to true and
+     * {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be set in the Uri
+     * parameters. See
+     * {@link Uri.Builder#appendQueryParameter(java.lang.String, java.lang.String)}
+     * for details on adding parameters. Sync adapters have write access to more
+     * columns but are restricted to a single account at a time. Calendars are
+     * designed to be primarily managed by a sync adapter and inserting new
+     * calendars should be done as a sync adapter. For the most part, apps
+     * should only update calendars (such as changing the color or display
+     * name). If a local calendar is required an app can do so by inserting as a
+     * sync adapter and using an {@link #ACCOUNT_TYPE} of
+     * {@link #ACCOUNT_TYPE_LOCAL} .
+     * <dl>
+     * <dt><b>Insert</b></dt>
+     * <dd>When inserting a new calendar the following fields must be included:
+     * <ul>
+     * <li>{@link #ACCOUNT_NAME}</li>
+     * <li>{@link #ACCOUNT_TYPE}</li>
+     * <li>{@link #NAME}</li>
+     * <li>{@link #CALENDAR_DISPLAY_NAME}</li>
+     * <li>{@link #CALENDAR_COLOR}</li>
+     * <li>{@link #CALENDAR_ACCESS_LEVEL}</li>
+     * <li>{@link #OWNER_ACCOUNT}</li>
+     * </ul>
+     * The following fields are not required when inserting a Calendar but are
+     * generally a good idea to include:
+     * <ul>
+     * <li>{@link #SYNC_EVENTS} set to 1</li>
+     * <li>{@link #CALENDAR_TIME_ZONE}</li>
+     * <li>{@link #ALLOWED_REMINDERS}</li>
+     * </ul>
+     * <dt><b>Update</b></dt>
+     * <dd>To perform an update on a calendar the {@link #_ID} of the calendar
+     * should be provided either as an appended id to the Uri (
+     * {@link ContentUris#withAppendedId}) or as the first selection item--the
+     * selection should start with "_id=?" and the first selectionArg should be
+     * the _id of the calendar. Calendars may also be updated using a selection
+     * without the id. In general, the {@link #ACCOUNT_NAME} and
+     * {@link #ACCOUNT_TYPE} should not be changed after a calendar is created
+     * as this can cause issues for sync adapters.
+     * <dt><b>Delete</b></dt>
+     * <dd>Calendars can be deleted either by the {@link #_ID} as an appended id
+     * on the Uri or using any standard selection. Deleting a calendar should
+     * generally be handled by a sync adapter as it will remove the calendar
+     * from the database and all associated data (aka events).</dd>
+     * <dt><b>Query</b></dt>
+     * <dd>Querying the Calendars table will get you all information about a set
+     * of calendars. There will be one row returned for each calendar that
+     * matches the query selection, or at most a single row if the {@link #_ID}
+     * is appended to the Uri.</dd>
+     * </dl>
+     * <h3>Calendar Columns</h3> The following Calendar columns are writable by
+     * both an app and a sync adapter.
+     * <ul>
+     * <li>{@link #NAME}</li>
+     * <li>{@link #CALENDAR_DISPLAY_NAME}</li>
+     * <li>{@link #CALENDAR_COLOR}</li>
+     * <li>{@link #VISIBLE}</li>
+     * <li>{@link #SYNC_EVENTS}</li>
+     * </ul>
+     * The following Calendars columns are writable only by a sync adapter
+     * <ul>
+     * <li>{@link #ACCOUNT_NAME}</li>
+     * <li>{@link #ACCOUNT_TYPE}</li>
+     * <li>{@link #_SYNC_ID}</li>
+     * <li>{@link #DIRTY}</li>
+     * <li>{@link #OWNER_ACCOUNT}</li>
+     * <li>{@link #MAX_REMINDERS}</li>
+     * <li>{@link #ALLOWED_REMINDERS}</li>
+     * <li>{@link #CAN_MODIFY_TIME_ZONE}</li>
+     * <li>{@link #CAN_ORGANIZER_RESPOND}</li>
+     * <li>{@link #CAN_PARTIALLY_UPDATE}</li>
+     * <li>{@link #CALENDAR_LOCATION}</li>
+     * <li>{@link #CALENDAR_TIME_ZONE}</li>
+     * <li>{@link #CALENDAR_ACCESS_LEVEL}</li>
+     * <li>{@link #DELETED}</li>
+     * <li>{@link #CAL_SYNC1}</li>
+     * <li>{@link #CAL_SYNC2}</li>
+     * <li>{@link #CAL_SYNC3}</li>
+     * <li>{@link #CAL_SYNC4}</li>
+     * <li>{@link #CAL_SYNC5}</li>
+     * <li>{@link #CAL_SYNC6}</li>
+     * <li>{@link #CAL_SYNC7}</li>
+     * <li>{@link #CAL_SYNC8}</li>
+     * <li>{@link #CAL_SYNC9}</li>
+     * <li>{@link #CAL_SYNC10}</li>
+     * </ul>
      */
     public static class Calendars implements BaseColumns, SyncColumns, CalendarsColumns {
         private static final String WHERE_DELETE_FOR_ACCOUNT = Calendars.ACCOUNT_NAME + "=?"
@@ -569,6 +658,7 @@
             DIRTY,
             OWNER_ACCOUNT,
             MAX_REMINDERS,
+            ALLOWED_REMINDERS,
             CAN_MODIFY_TIME_ZONE,
             CAN_ORGANIZER_RESPOND,
             CAN_PARTIALLY_UPDATE,
@@ -1252,13 +1342,15 @@
     }
 
     /**
-     * Constants and helpers for the Events table, which contains details of a
-     * single event. <h3>Operations</h3> All operations can be done either as an
-     * app or as a sync adapter. To perform an operation as a sync adapter
-     * {@link #CALLER_IS_SYNCADAPTER} should be set to true in the Uri
-     * parameters and {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be
-     * set. Sync adapters have write access to more columns but are restricted
-     * to a single account at a time.
+     * Constants and helpers for the Events table, which contains details for
+     * individual events. <h3>Operations</h3> All operations can be done either
+     * as an app or as a sync adapter. To perform an operation as a sync adapter
+     * {@link #CALLER_IS_SYNCADAPTER} should be set to true and
+     * {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be set in the Uri
+     * parameters. See
+     * {@link Uri.Builder#appendQueryParameter(java.lang.String, java.lang.String)}
+     * for details on adding parameters. Sync adapters have write access to more
+     * columns but are restricted to a single account at a time.
      * <dl>
      * <dt><b>Insert</b></dt>
      * <dd>When inserting a new event the following fields must be included:
@@ -1270,13 +1362,14 @@
      * There are also further requirements when inserting or updating an event.
      * See the section on Writing to Events.</dd>
      * <dt><b>Update</b></dt>
-     * <dd>To perform an update on an Event the {@link Events#_ID} of the event
-     * must be provided either as an appended id to the Uri (
+     * <dd>To perform an update of an Event the {@link Events#_ID} of the event
+     * should be provided either as an appended id to the Uri (
      * {@link ContentUris#withAppendedId}) or as the first selection item--the
      * selection should start with "_id=?" and the first selectionArg should be
-     * the _id of the event. Updating an event must respect the same rules as
-     * inserting and is further restricted in the fields that can be written.
-     * See the section on Writing to Events.</dd>
+     * the _id of the event. Updates may also be done using a selection and no
+     * id. Updating an event must respect the same rules as inserting and is
+     * further restricted in the fields that can be written. See the section on
+     * Writing to Events.</dd>
      * <dt><b>Delete</b></dt>
      * <dd>Events can be deleted either by the {@link Events#_ID} as an appended
      * id on the Uri or using any standard selection. If an appended id is used
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eb0b7d0..888f0c0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8740,6 +8740,10 @@
         }
         jumpDrawablesToCurrentState();
         resolveLayoutDirection();
+        if (isFocused()) {
+            InputMethodManager imm = InputMethodManager.peekInstance();
+            imm.focusIn(this);
+        }
     }
 
     /**
@@ -11705,7 +11709,7 @@
 
     /**
      * Utility to return a default size. Uses the supplied size if the
-     * MeasureSpec imposed no contraints. Will get larger if allowed
+     * MeasureSpec imposed no constraints. Will get larger if allowed
      * by the MeasureSpec.
      *
      * @param size Default size for this view
@@ -11715,7 +11719,7 @@
     public static int getDefaultSize(int size, int measureSpec) {
         int result = size;
         int specMode = MeasureSpec.getMode(measureSpec);
-        int specSize =  MeasureSpec.getSize(measureSpec);
+        int specSize = MeasureSpec.getSize(measureSpec);
 
         switch (specMode) {
         case MeasureSpec.UNSPECIFIED:
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index a15ca0c..4a514bf 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -38,8 +38,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.UNSPECIFIED;
 import static java.lang.Math.max;
 import static java.lang.Math.min;
 
@@ -760,43 +758,6 @@
 
     // Measurement
 
-    private static int getChildMeasureSpec2(int spec, int padding, int childDimension) {
-        int resultSize;
-        int resultMode;
-
-        if (childDimension >= 0) {
-            resultSize = childDimension;
-            resultMode = EXACTLY;
-        } else {
-            /*
-            using the following lines would replicate the logic of ViewGroup.getChildMeasureSpec()
-
-            int specMode = MeasureSpec.getMode(spec);
-            int specSize = MeasureSpec.getSize(spec);
-            int size = Math.max(0, specSize - padding);
-
-            resultSize = size;
-            resultMode = (specMode == EXACTLY && childDimension == LayoutParams.WRAP_CONTENT) ?
-                    AT_MOST : specMode;
-            */
-            resultSize = 0;
-            resultMode = UNSPECIFIED;
-        }
-        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
-    }
-
-    @Override
-    protected void measureChild(View child, int parentWidthSpec, int parentHeightSpec) {
-        ViewGroup.LayoutParams lp = child.getLayoutParams();
-
-        int childWidthMeasureSpec = getChildMeasureSpec2(parentWidthSpec,
-                mPaddingLeft + mPaddingRight, lp.width);
-        int childHeightMeasureSpec = getChildMeasureSpec2(parentHeightSpec,
-                mPaddingTop + mPaddingBottom, lp.height);
-
-        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-    }
-
     @Override
     protected void onMeasure(int widthSpec, int heightSpec) {
         measureChildren(widthSpec, heightSpec);
@@ -1145,9 +1106,6 @@
             return result;
         }
 
-        /*
-        Topological sort.
-         */
         private Arc[] topologicalSort(final Arc[] arcs, int start) {
         // todo ensure the <start> vertex is added in edge cases
             final List<Arc> result = new ArrayList<Arc>();
@@ -2214,7 +2172,9 @@
          *
          * @param view              the view to which this alignment should be applied
          * @param viewSize          the measured size of the view
-         * @param measurementType   the type of measurement that should be made
+         * @param measurementType   The type of measurement that should be made. This feature
+         *                          is currently unused as GridLayout only supports one
+         *                          type of measurement: {@link View#measure(int, int)}.
          *
          * @return                  the alignment value
          */
@@ -2230,7 +2190,9 @@
          * @param view              the view to which this alignment should be applied
          * @param viewSize          the measured size of the view
          * @param cellSize          the size of the cell into which this view will be placed
-         * @param measurementType   the type of measurement that should be made
+         * @param measurementType   The type of measurement that should be made. This feature
+         *                          is currently unused as GridLayout only supports one
+         *                          type of measurement: {@link View#measure(int, int)}.
          *
          * @return                  the aligned size
          */
diff --git a/core/java/android/widget/Space.java b/core/java/android/widget/Space.java
index d98b937..d7b2ec2 100644
--- a/core/java/android/widget/Space.java
+++ b/core/java/android/widget/Space.java
@@ -72,4 +72,35 @@
     public void setLayoutParams(ViewGroup.LayoutParams params) {
         super.setLayoutParams(params);
     }
+
+    /**
+     * Compare to: {@link View#getDefaultSize(int, int)}
+     * If mode is AT_MOST, return the child size instead of the parent size
+     * (unless it is too big).
+     */
+    private static int getDefaultSize2(int size, int measureSpec) {
+        int result = size;
+        int specMode = MeasureSpec.getMode(measureSpec);
+        int specSize = MeasureSpec.getSize(measureSpec);
+
+        switch (specMode) {
+            case MeasureSpec.UNSPECIFIED:
+                result = size;
+                break;
+            case MeasureSpec.AT_MOST:
+                result = Math.min(size, specSize);
+                break;
+            case MeasureSpec.EXACTLY:
+                result = specSize;
+                break;
+        }
+        return result;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        setMeasuredDimension(
+                getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
+                getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
+    }
 }
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 18d9ec4..773be5b 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -16,8 +16,12 @@
 
 package com.android.internal.net;
 
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 
 /**
  * A simple container used to carry information in VpnBuilder, VpnDialogs,
@@ -27,6 +31,30 @@
  */
 public class VpnConfig implements Parcelable {
 
+    public static final String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED";
+
+    public static void enforceCallingPackage(String packageName) {
+        if (!"com.android.vpndialogs".equals(packageName)) {
+            throw new SecurityException("Unauthorized Caller");
+        }
+    }
+
+    public static Intent getIntentForConfirmation() {
+        Intent intent = new Intent();
+        intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ConfirmDialog");
+        return intent;
+    }
+
+    public static PendingIntent getIntentForNotification(Context context, VpnConfig config) {
+        config.startTime = SystemClock.elapsedRealtime();
+        Intent intent = new Intent();
+        intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ManageDialog");
+        intent.putExtra("config", config);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
+                Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+    }
+
     public String packageName;
     public String sessionName;
     public String interfaceName;
diff --git a/core/java/com/android/internal/util/HanziToPinyin.java b/core/java/com/android/internal/util/HanziToPinyin.java
deleted file mode 100644
index 6a4adaa..0000000
--- a/core/java/com/android/internal/util/HanziToPinyin.java
+++ /dev/null
@@ -1,495 +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.internal.util;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Locale;
-
-/**
- * An object to convert Chinese character to its corresponding pinyin string.
- * For characters with multiple possible pinyin string, only one is selected
- * according to collator. Polyphone is not supported in this implementation.
- * This class is implemented to achieve the best runtime performance and minimum
- * runtime resources with tolerable sacrifice of accuracy. This implementation
- * highly depends on zh_CN ICU collation data and must be always synchronized with
- * ICU.
- */
-public class HanziToPinyin {
-    private static final String TAG = "HanziToPinyin";
-
-    private static final char[] UNIHANS = {
-            '\u5416', '\u54ce', '\u5b89', '\u80ae', '\u51f9', '\u516b', '\u63b0', '\u6273',
-            '\u90a6', '\u52f9', '\u9642', '\u5954', '\u4f3b', '\u7680', '\u782d', '\u706c',
-            '\u618b', '\u6c43', '\u51ab', '\u7676', '\u5cec', '\u5693', '\u5072', '\u53c2',
-            '\u4ed3', '\u64a1', '\u518a', '\u5d7e', '\u564c', '\u6260', '\u62c6', '\u8fbf',
-            '\u4f25', '\u6284', '\u8f66', '\u62bb', '\u9637', '\u5403', '\u5145', '\u62bd',
-            '\u51fa', '\u640b', '\u5ddb', '\u5205', '\u5439', '\u65fe', '\u8e14', '\u5472',
-            '\u4ece', '\u51d1', '\u7c97', '\u6c46', '\u5d14', '\u90a8', '\u6413', '\u5491',
-            '\u5446', '\u4e39', '\u5f53', '\u5200', '\u6074', '\u6265', '\u706f', '\u4efe',
-            '\u55f2', '\u6541', '\u5201', '\u7239', '\u4e01', '\u4e1f', '\u4e1c', '\u543a',
-            '\u5262', '\u8011', '\u5796', '\u5428', '\u591a', '\u59b8', '\u5940', '\u97a5',
-            '\u800c', '\u53d1', '\u5e06', '\u531a', '\u98de', '\u5206', '\u4e30', '\u8985',
-            '\u4ecf', '\u57ba', '\u7d11', '\u592b', '\u7324', '\u65ee', '\u4f85', '\u5e72',
-            '\u5188', '\u768b', '\u6208', '\u7ed9', '\u6839', '\u63ef', '\u55bc', '\u55f0',
-            '\u5de5', '\u52fe', '\u4f30', '\u9e39', '\u4e56', '\u5173', '\u5149', '\u5f52',
-            '\u4e28', '\u8b34', '\u5459', '\u598e', '\u548d', '\u4f44', '\u592f', '\u8320',
-            '\u8bc3', '\u9ed2', '\u62eb', '\u4ea8', '\u53ff', '\u9f41', '\u4e4e', '\u82b1',
-            '\u6000', '\u6b22', '\u5ddf', '\u7070', '\u660f', '\u5419', '\u4e0c', '\u52a0',
-            '\u620b', '\u6c5f', '\u827d', '\u9636', '\u5dfe', '\u5755', '\u5182', '\u4e29',
-            '\u51e5', '\u59e2', '\u5658', '\u519b', '\u5494', '\u5f00', '\u938e', '\u5ffc',
-            '\u5c3b', '\u533c', '\u808e', '\u52a5', '\u7a7a', '\u62a0', '\u625d', '\u5938',
-            '\u84af', '\u5bbd', '\u5321', '\u4e8f', '\u5764', '\u6269', '\u62c9', '\u4f86',
-            '\u5170', '\u5577', '\u635e', '\u4ec2', '\u96f7', '\u8137', '\u68f1', '\u695e',
-            '\u550e', '\u4fe9', '\u5afe', '\u826f', '\u8e7d', '\u57d3', '\u53b8', '\u62ce',
-            '\u6e9c', '\u9f99', '\u5a04', '\u565c', '\u5b6a', '\u62a1', '\u9831', '\u5988',
-            '\u57cb', '\u989f', '\u7264', '\u732b', '\u5445', '\u95e8', '\u6c13', '\u54aa',
-            '\u5b80', '\u55b5', '\u4e5c', '\u6c11', '\u540d', '\u8c2c', '\u6478', '\u725f',
-            '\u6bcd', '\u62cf', '\u8149', '\u56e1', '\u56d4', '\u5b6c', '\u8bb7', '\u5a1e',
-            '\u5ae9', '\u80fd', '\u92b0', '\u62c8', '\u5a18', '\u9e1f', '\u634f', '\u56dc',
-            '\u5b81', '\u599e', '\u519c', '\u7fba', '\u5974', '\u597b', '\u9ec1', '\u90cd',
-            '\u5662', '\u8bb4', '\u5991', '\u62cd', '\u7705', '\u6c78', '\u629b', '\u5478',
-            '\u55b7', '\u5309', '\u4e76', '\u7247', '\u527d', '\u6c15', '\u59d8', '\u4e52',
-            '\u948b', '\u5256', '\u4ec6', '\u4e03', '\u6390', '\u5343', '\u545b', '\u6084',
-            '\u5207', '\u4eb2', '\u9751', '\u5b86', '\u74d7', '\u533a', '\u5cd1', '\u7094',
-            '\u590b', '\u5465', '\u7a63', '\u835b', '\u60f9', '\u4eba', '\u6254', '\u65e5',
-            '\u620e', '\u53b9', '\u909a', '\u5827', '\u6875', '\u95f0', '\u633c', '\u4ee8',
-            '\u6be2', '\u4e09', '\u6852', '\u63bb', '\u8272', '\u68ee', '\u50e7', '\u6740',
-            '\u7b5b', '\u5c71', '\u4f24', '\u5f30', '\u5962', '\u7533', '\u5347', '\u5c38',
-            '\u53ce', '\u4e66', '\u5237', '\u8870', '\u95e9', '\u53cc', '\u8c01', '\u542e',
-            '\u8bf4', '\u53b6', '\u5fea', '\u51c1', '\u82cf', '\u72fb', '\u590a', '\u5b59',
-            '\u5506', '\u4ed6', '\u5b61', '\u574d', '\u6c64', '\u5932', '\u5fd1', '\u81af',
-            '\u5254', '\u5929', '\u65eb', '\u6017', '\u5385', '\u70b5', '\u5077', '\u51f8',
-            '\u6e4d', '\u63a8', '\u541e', '\u8bac', '\u52b8', '\u6b6a', '\u5f2f', '\u5c23',
-            '\u5371', '\u6637', '\u7fc1', '\u631d', '\u4e4c', '\u5915', '\u5477', '\u4ed9',
-            '\u4e61', '\u7071', '\u4e9b', '\u5fc3', '\u5174', '\u51f6', '\u4f11', '\u620c',
-            '\u5405', '\u75b6', '\u7025', '\u4e2b', '\u54bd', '\u592e', '\u5e7a', '\u503b',
-            '\u4e00', '\u4e5a', '\u5e94', '\u5537', '\u4f63', '\u4f18', '\u7ea1', '\u56e6',
-            '\u66f0', '\u8480', '\u5e00', '\u707d', '\u5142', '\u7242', '\u50ae', '\u556b',
-            '\u9c61', '\u600e', '\u66fd', '\u5412', '\u635a', '\u6cbe', '\u5f20', '\u4f4b',
-            '\u8707', '\u8d1e', '\u9eee', '\u4e4b', '\u4e2d', '\u5dde', '\u6731', '\u6293',
-            '\u62fd', '\u4e13', '\u5986', '\u96b9', '\u5b92', '\u5353', '\u4ed4', '\u5b97',
-            '\u90b9', '\u79df', '\u5297', '\u55fa', '\u5c0a', '\u6628',
-        };
-    private final static byte[][] PINYINS = {
-            {65, 00, 00, 00, 00, 00, }, {65, 73, 00, 00, 00, 00, },
-            {65, 78, 00, 00, 00, 00, }, {65, 78, 71, 00, 00, 00, },
-            {65, 79, 00, 00, 00, 00, }, {66, 65, 00, 00, 00, 00, },
-            {66, 65, 73, 00, 00, 00, }, {66, 65, 78, 00, 00, 00, },
-            {66, 65, 78, 71, 00, 00, }, {66, 65, 79, 00, 00, 00, },
-            {66, 69, 73, 00, 00, 00, }, {66, 69, 78, 00, 00, 00, },
-            {66, 69, 78, 71, 00, 00, }, {66, 73, 00, 00, 00, 00, },
-            {66, 73, 65, 78, 00, 00, }, {66, 73, 65, 79, 00, 00, },
-            {66, 73, 69, 00, 00, 00, }, {66, 73, 78, 00, 00, 00, },
-            {66, 73, 78, 71, 00, 00, }, {66, 79, 00, 00, 00, 00, },
-            {66, 85, 00, 00, 00, 00, }, {67, 65, 00, 00, 00, 00, },
-            {67, 65, 73, 00, 00, 00, }, {67, 65, 78, 00, 00, 00, },
-            {67, 65, 78, 71, 00, 00, }, {67, 65, 79, 00, 00, 00, },
-            {67, 69, 00, 00, 00, 00, }, {67, 69, 78, 00, 00, 00, },
-            {67, 69, 78, 71, 00, 00, }, {67, 72, 65, 00, 00, 00, },
-            {67, 72, 65, 73, 00, 00, }, {67, 72, 65, 78, 00, 00, },
-            {67, 72, 65, 78, 71, 00, }, {67, 72, 65, 79, 00, 00, },
-            {67, 72, 69, 00, 00, 00, }, {67, 72, 69, 78, 00, 00, },
-            {67, 72, 69, 78, 71, 00, }, {67, 72, 73, 00, 00, 00, },
-            {67, 72, 79, 78, 71, 00, }, {67, 72, 79, 85, 00, 00, },
-            {67, 72, 85, 00, 00, 00, }, {67, 72, 85, 65, 73, 00, },
-            {67, 72, 85, 65, 78, 00, }, {67, 72, 85, 65, 78, 71, },
-            {67, 72, 85, 73, 00, 00, }, {67, 72, 85, 78, 00, 00, },
-            {67, 72, 85, 79, 00, 00, }, {67, 73, 00, 00, 00, 00, },
-            {67, 79, 78, 71, 00, 00, }, {67, 79, 85, 00, 00, 00, },
-            {67, 85, 00, 00, 00, 00, }, {67, 85, 65, 78, 00, 00, },
-            {67, 85, 73, 00, 00, 00, }, {67, 85, 78, 00, 00, 00, },
-            {67, 85, 79, 00, 00, 00, }, {68, 65, 00, 00, 00, 00, },
-            {68, 65, 73, 00, 00, 00, }, {68, 65, 78, 00, 00, 00, },
-            {68, 65, 78, 71, 00, 00, }, {68, 65, 79, 00, 00, 00, },
-            {68, 69, 00, 00, 00, 00, }, {68, 69, 78, 00, 00, 00, },
-            {68, 69, 78, 71, 00, 00, }, {68, 73, 00, 00, 00, 00, },
-            {68, 73, 65, 00, 00, 00, }, {68, 73, 65, 78, 00, 00, },
-            {68, 73, 65, 79, 00, 00, }, {68, 73, 69, 00, 00, 00, },
-            {68, 73, 78, 71, 00, 00, }, {68, 73, 85, 00, 00, 00, },
-            {68, 79, 78, 71, 00, 00, }, {68, 79, 85, 00, 00, 00, },
-            {68, 85, 00, 00, 00, 00, }, {68, 85, 65, 78, 00, 00, },
-            {68, 85, 73, 00, 00, 00, }, {68, 85, 78, 00, 00, 00, },
-            {68, 85, 79, 00, 00, 00, }, {69, 00, 00, 00, 00, 00, },
-            {69, 78, 00, 00, 00, 00, }, {69, 78, 71, 00, 00, 00, },
-            {69, 82, 00, 00, 00, 00, }, {70, 65, 00, 00, 00, 00, },
-            {70, 65, 78, 00, 00, 00, }, {70, 65, 78, 71, 00, 00, },
-            {70, 69, 73, 00, 00, 00, }, {70, 69, 78, 00, 00, 00, },
-            {70, 69, 78, 71, 00, 00, }, {70, 73, 65, 79, 00, 00, },
-            {70, 79, 00, 00, 00, 00, }, {70, 85, 00, 00, 00, 00, },
-            {70, 79, 85, 00, 00, 00, }, {70, 85, 00, 00, 00, 00, },
-            {71, 85, 73, 00, 00, 00, }, {71, 65, 00, 00, 00, 00, },
-            {71, 65, 73, 00, 00, 00, }, {71, 65, 78, 00, 00, 00, },
-            {71, 65, 78, 71, 00, 00, }, {71, 65, 79, 00, 00, 00, },
-            {71, 69, 00, 00, 00, 00, }, {71, 69, 73, 00, 00, 00, },
-            {71, 69, 78, 00, 00, 00, }, {71, 69, 78, 71, 00, 00, },
-            {74, 73, 69, 00, 00, 00, }, {71, 69, 00, 00, 00, 00, },
-            {71, 79, 78, 71, 00, 00, }, {71, 79, 85, 00, 00, 00, },
-            {71, 85, 00, 00, 00, 00, }, {71, 85, 65, 00, 00, 00, },
-            {71, 85, 65, 73, 00, 00, }, {71, 85, 65, 78, 00, 00, },
-            {71, 85, 65, 78, 71, 00, }, {71, 85, 73, 00, 00, 00, },
-            {71, 85, 78, 00, 00, 00, }, {71, 85, 65, 78, 00, 00, },
-            {71, 85, 79, 00, 00, 00, }, {72, 65, 00, 00, 00, 00, },
-            {72, 65, 73, 00, 00, 00, }, {72, 65, 78, 00, 00, 00, },
-            {72, 65, 78, 71, 00, 00, }, {72, 65, 79, 00, 00, 00, },
-            {72, 69, 00, 00, 00, 00, }, {72, 69, 73, 00, 00, 00, },
-            {72, 69, 78, 00, 00, 00, }, {72, 69, 78, 71, 00, 00, },
-            {72, 79, 78, 71, 00, 00, }, {72, 79, 85, 00, 00, 00, },
-            {72, 85, 00, 00, 00, 00, }, {72, 85, 65, 00, 00, 00, },
-            {72, 85, 65, 73, 00, 00, }, {72, 85, 65, 78, 00, 00, },
-            {72, 85, 65, 78, 71, 00, }, {72, 85, 73, 00, 00, 00, },
-            {72, 85, 78, 00, 00, 00, }, {72, 85, 79, 00, 00, 00, },
-            {74, 73, 00, 00, 00, 00, }, {74, 73, 65, 00, 00, 00, },
-            {74, 73, 65, 78, 00, 00, }, {74, 73, 65, 78, 71, 00, },
-            {74, 73, 65, 79, 00, 00, }, {74, 73, 69, 00, 00, 00, },
-            {74, 73, 78, 00, 00, 00, }, {74, 73, 78, 71, 00, 00, },
-            {74, 73, 79, 78, 71, 00, }, {74, 73, 85, 00, 00, 00, },
-            {74, 85, 00, 00, 00, 00, }, {74, 85, 65, 78, 00, 00, },
-            {74, 85, 69, 00, 00, 00, }, {74, 85, 78, 00, 00, 00, },
-            {75, 65, 00, 00, 00, 00, }, {75, 65, 73, 00, 00, 00, },
-            {75, 65, 78, 00, 00, 00, }, {75, 65, 78, 71, 00, 00, },
-            {75, 65, 79, 00, 00, 00, }, {75, 69, 00, 00, 00, 00, },
-            {75, 69, 78, 00, 00, 00, }, {75, 69, 78, 71, 00, 00, },
-            {75, 79, 78, 71, 00, 00, }, {75, 79, 85, 00, 00, 00, },
-            {75, 85, 00, 00, 00, 00, }, {75, 85, 65, 00, 00, 00, },
-            {75, 85, 65, 73, 00, 00, }, {75, 85, 65, 78, 00, 00, },
-            {75, 85, 65, 78, 71, 00, }, {75, 85, 73, 00, 00, 00, },
-            {75, 85, 78, 00, 00, 00, }, {75, 85, 79, 00, 00, 00, },
-            {76, 65, 00, 00, 00, 00, }, {76, 65, 73, 00, 00, 00, },
-            {76, 65, 78, 00, 00, 00, }, {76, 65, 78, 71, 00, 00, },
-            {76, 65, 79, 00, 00, 00, }, {76, 69, 00, 00, 00, 00, },
-            {76, 69, 73, 00, 00, 00, }, {76, 73, 00, 00, 00, 00, },
-            {76, 73, 78, 71, 00, 00, }, {76, 69, 78, 71, 00, 00, },
-            {76, 73, 00, 00, 00, 00, }, {76, 73, 65, 00, 00, 00, },
-            {76, 73, 65, 78, 00, 00, }, {76, 73, 65, 78, 71, 00, },
-            {76, 73, 65, 79, 00, 00, }, {76, 73, 69, 00, 00, 00, },
-            {76, 73, 78, 00, 00, 00, }, {76, 73, 78, 71, 00, 00, },
-            {76, 73, 85, 00, 00, 00, }, {76, 79, 78, 71, 00, 00, },
-            {76, 79, 85, 00, 00, 00, }, {76, 85, 00, 00, 00, 00, },
-            {76, 85, 65, 78, 00, 00, }, {76, 85, 78, 00, 00, 00, },
-            {76, 85, 79, 00, 00, 00, }, {77, 65, 00, 00, 00, 00, },
-            {77, 65, 73, 00, 00, 00, }, {77, 65, 78, 00, 00, 00, },
-            {77, 65, 78, 71, 00, 00, }, {77, 65, 79, 00, 00, 00, },
-            {77, 69, 73, 00, 00, 00, }, {77, 69, 78, 00, 00, 00, },
-            {77, 69, 78, 71, 00, 00, }, {77, 73, 00, 00, 00, 00, },
-            {77, 73, 65, 78, 00, 00, }, {77, 73, 65, 79, 00, 00, },
-            {77, 73, 69, 00, 00, 00, }, {77, 73, 78, 00, 00, 00, },
-            {77, 73, 78, 71, 00, 00, }, {77, 73, 85, 00, 00, 00, },
-            {77, 79, 00, 00, 00, 00, }, {77, 79, 85, 00, 00, 00, },
-            {77, 85, 00, 00, 00, 00, }, {78, 65, 00, 00, 00, 00, },
-            {78, 65, 73, 00, 00, 00, }, {78, 65, 78, 00, 00, 00, },
-            {78, 65, 78, 71, 00, 00, }, {78, 65, 79, 00, 00, 00, },
-            {78, 69, 00, 00, 00, 00, }, {78, 69, 73, 00, 00, 00, },
-            {78, 69, 78, 00, 00, 00, }, {78, 69, 78, 71, 00, 00, },
-            {78, 73, 00, 00, 00, 00, }, {78, 73, 65, 78, 00, 00, },
-            {78, 73, 65, 78, 71, 00, }, {78, 73, 65, 79, 00, 00, },
-            {78, 73, 69, 00, 00, 00, }, {78, 73, 78, 00, 00, 00, },
-            {78, 73, 78, 71, 00, 00, }, {78, 73, 85, 00, 00, 00, },
-            {78, 79, 78, 71, 00, 00, }, {78, 79, 85, 00, 00, 00, },
-            {78, 85, 00, 00, 00, 00, }, {78, 85, 65, 78, 00, 00, },
-            {78, 85, 78, 00, 00, 00, }, {78, 85, 79, 00, 00, 00, },
-            {79, 00, 00, 00, 00, 00, }, {79, 85, 00, 00, 00, 00, },
-            {80, 65, 00, 00, 00, 00, }, {80, 65, 73, 00, 00, 00, },
-            {80, 65, 78, 00, 00, 00, }, {80, 65, 78, 71, 00, 00, },
-            {80, 65, 79, 00, 00, 00, }, {80, 69, 73, 00, 00, 00, },
-            {80, 69, 78, 00, 00, 00, }, {80, 69, 78, 71, 00, 00, },
-            {80, 73, 00, 00, 00, 00, }, {80, 73, 65, 78, 00, 00, },
-            {80, 73, 65, 79, 00, 00, }, {80, 73, 69, 00, 00, 00, },
-            {80, 73, 78, 00, 00, 00, }, {80, 73, 78, 71, 00, 00, },
-            {80, 79, 00, 00, 00, 00, }, {80, 79, 85, 00, 00, 00, },
-            {80, 85, 00, 00, 00, 00, }, {81, 73, 00, 00, 00, 00, },
-            {81, 73, 65, 00, 00, 00, }, {81, 73, 65, 78, 00, 00, },
-            {81, 73, 65, 78, 71, 00, }, {81, 73, 65, 79, 00, 00, },
-            {81, 73, 69, 00, 00, 00, }, {81, 73, 78, 00, 00, 00, },
-            {81, 73, 78, 71, 00, 00, }, {81, 73, 79, 78, 71, 00, },
-            {81, 73, 85, 00, 00, 00, }, {81, 85, 00, 00, 00, 00, },
-            {81, 85, 65, 78, 00, 00, }, {81, 85, 69, 00, 00, 00, },
-            {81, 85, 78, 00, 00, 00, }, {82, 65, 78, 00, 00, 00, },
-            {82, 65, 78, 71, 00, 00, }, {82, 65, 79, 00, 00, 00, },
-            {82, 69, 00, 00, 00, 00, }, {82, 69, 78, 00, 00, 00, },
-            {82, 69, 78, 71, 00, 00, }, {82, 73, 00, 00, 00, 00, },
-            {82, 79, 78, 71, 00, 00, }, {82, 79, 85, 00, 00, 00, },
-            {82, 85, 00, 00, 00, 00, }, {82, 85, 65, 78, 00, 00, },
-            {82, 85, 73, 00, 00, 00, }, {82, 85, 78, 00, 00, 00, },
-            {82, 85, 79, 00, 00, 00, }, {83, 65, 00, 00, 00, 00, },
-            {83, 65, 73, 00, 00, 00, }, {83, 65, 78, 00, 00, 00, },
-            {83, 65, 78, 71, 00, 00, }, {83, 65, 79, 00, 00, 00, },
-            {83, 69, 00, 00, 00, 00, }, {83, 69, 78, 00, 00, 00, },
-            {83, 69, 78, 71, 00, 00, }, {83, 72, 65, 00, 00, 00, },
-            {83, 72, 65, 73, 00, 00, }, {83, 72, 65, 78, 00, 00, },
-            {83, 72, 65, 78, 71, 00, }, {83, 72, 65, 79, 00, 00, },
-            {83, 72, 69, 00, 00, 00, }, {83, 72, 69, 78, 00, 00, },
-            {83, 72, 69, 78, 71, 00, }, {83, 72, 73, 00, 00, 00, },
-            {83, 72, 79, 85, 00, 00, }, {83, 72, 85, 00, 00, 00, },
-            {83, 72, 85, 65, 00, 00, }, {83, 72, 85, 65, 73, 00, },
-            {83, 72, 85, 65, 78, 00, }, {83, 72, 85, 65, 78, 71, },
-            {83, 72, 85, 73, 00, 00, }, {83, 72, 85, 78, 00, 00, },
-            {83, 72, 85, 79, 00, 00, }, {83, 73, 00, 00, 00, 00, },
-            {83, 79, 78, 71, 00, 00, }, {83, 79, 85, 00, 00, 00, },
-            {83, 85, 00, 00, 00, 00, }, {83, 85, 65, 78, 00, 00, },
-            {83, 85, 73, 00, 00, 00, }, {83, 85, 78, 00, 00, 00, },
-            {83, 85, 79, 00, 00, 00, }, {84, 65, 00, 00, 00, 00, },
-            {84, 65, 73, 00, 00, 00, }, {84, 65, 78, 00, 00, 00, },
-            {84, 65, 78, 71, 00, 00, }, {84, 65, 79, 00, 00, 00, },
-            {84, 69, 00, 00, 00, 00, }, {84, 69, 78, 71, 00, 00, },
-            {84, 73, 00, 00, 00, 00, }, {84, 73, 65, 78, 00, 00, },
-            {84, 73, 65, 79, 00, 00, }, {84, 73, 69, 00, 00, 00, },
-            {84, 73, 78, 71, 00, 00, }, {84, 79, 78, 71, 00, 00, },
-            {84, 79, 85, 00, 00, 00, }, {84, 85, 00, 00, 00, 00, },
-            {84, 85, 65, 78, 00, 00, }, {84, 85, 73, 00, 00, 00, },
-            {84, 85, 78, 00, 00, 00, }, {84, 85, 79, 00, 00, 00, },
-            {87, 65, 00, 00, 00, 00, }, {87, 65, 73, 00, 00, 00, },
-            {87, 65, 78, 00, 00, 00, }, {87, 65, 78, 71, 00, 00, },
-            {87, 69, 73, 00, 00, 00, }, {87, 69, 78, 00, 00, 00, },
-            {87, 69, 78, 71, 00, 00, }, {87, 79, 00, 00, 00, 00, },
-            {87, 85, 00, 00, 00, 00, }, {88, 73, 00, 00, 00, 00, },
-            {88, 73, 65, 00, 00, 00, }, {88, 73, 65, 78, 00, 00, },
-            {88, 73, 65, 78, 71, 00, }, {88, 73, 65, 79, 00, 00, },
-            {88, 73, 69, 00, 00, 00, }, {88, 73, 78, 00, 00, 00, },
-            {88, 73, 78, 71, 00, 00, }, {88, 73, 79, 78, 71, 00, },
-            {88, 73, 85, 00, 00, 00, }, {88, 85, 00, 00, 00, 00, },
-            {88, 85, 65, 78, 00, 00, }, {88, 85, 69, 00, 00, 00, },
-            {88, 85, 78, 00, 00, 00, }, {89, 65, 00, 00, 00, 00, },
-            {89, 65, 78, 00, 00, 00, }, {89, 65, 78, 71, 00, 00, },
-            {89, 65, 79, 00, 00, 00, }, {89, 69, 00, 00, 00, 00, },
-            {89, 73, 00, 00, 00, 00, }, {89, 73, 78, 00, 00, 00, },
-            {89, 73, 78, 71, 00, 00, }, {89, 79, 00, 00, 00, 00, },
-            {89, 79, 78, 71, 00, 00, }, {89, 79, 85, 00, 00, 00, },
-            {89, 85, 00, 00, 00, 00, }, {89, 85, 65, 78, 00, 00, },
-            {89, 85, 69, 00, 00, 00, }, {89, 85, 78, 00, 00, 00, },
-            {90, 65, 00, 00, 00, 00, }, {90, 65, 73, 00, 00, 00, },
-            {90, 65, 78, 00, 00, 00, }, {90, 65, 78, 71, 00, 00, },
-            {90, 65, 79, 00, 00, 00, }, {90, 69, 00, 00, 00, 00, },
-            {90, 69, 73, 00, 00, 00, }, {90, 69, 78, 00, 00, 00, },
-            {90, 69, 78, 71, 00, 00, }, {90, 72, 65, 00, 00, 00, },
-            {90, 72, 65, 73, 00, 00, }, {90, 72, 65, 78, 00, 00, },
-            {90, 72, 65, 78, 71, 00, }, {90, 72, 65, 79, 00, 00, },
-            {90, 72, 69, 00, 00, 00, }, {90, 72, 69, 78, 00, 00, },
-            {90, 72, 69, 78, 71, 00, }, {90, 72, 73, 00, 00, 00, },
-            {90, 72, 79, 78, 71, 00, }, {90, 72, 79, 85, 00, 00, },
-            {90, 72, 85, 00, 00, 00, }, {90, 72, 85, 65, 00, 00, },
-            {90, 72, 85, 65, 73, 00, }, {90, 72, 85, 65, 78, 00, },
-            {90, 72, 85, 65, 78, 71, }, {90, 72, 85, 73, 00, 00, },
-            {90, 72, 85, 78, 00, 00, }, {90, 72, 85, 79, 00, 00, },
-            {90, 73, 00, 00, 00, 00, }, {90, 79, 78, 71, 00, 00, },
-            {90, 79, 85, 00, 00, 00, }, {90, 85, 00, 00, 00, 00, },
-            {90, 85, 65, 78, 00, 00, }, {90, 85, 73, 00, 00, 00, },
-            {90, 85, 78, 00, 00, 00, }, {90, 85, 79, 00, 00, 00, },
-
-        };
-
-    /** First and last Chinese character with known Pinyin according to zh collation */
-    private static final String FIRST_PINYIN_UNIHAN =  "\u5416";
-    private static final String LAST_PINYIN_UNIHAN =  "\u5497";
-    /** The first Chinese character in Unicode block */
-    private static final char FIRST_UNIHAN = '\u3400';
-    private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA);
-
-    private static HanziToPinyin sInstance;
-    private final boolean mHasChinaCollator;
-
-    public static class Token {
-        /**
-         * Separator between target string for each source char
-         */
-        public static final String SEPARATOR = " ";
-
-        public static final int LATIN = 1;
-        public static final int PINYIN = 2;
-        public static final int UNKNOWN = 3;
-
-        public Token() {
-        }
-
-        public Token(int type, String source, String target) {
-            this.type = type;
-            this.source = source;
-            this.target = target;
-        }
-        /**
-         * Type of this token, ASCII, PINYIN or UNKNOWN.
-         */
-        public int type;
-        /**
-         * Original string before translation.
-         */
-        public String source;
-        /**
-         * Translated string of source. For Han, target is corresponding Pinyin.
-         * Otherwise target is original string in source.
-         */
-        public String target;
-    }
-
-    protected HanziToPinyin(boolean hasChinaCollator) {
-        mHasChinaCollator = hasChinaCollator;
-    }
-
-    public static HanziToPinyin getInstance() {
-        synchronized(HanziToPinyin.class) {
-            if (sInstance != null) {
-                return sInstance;
-            }
-            // Check if zh_CN collation data is available
-            final Locale locale[] = Collator.getAvailableLocales();
-            for (int i = 0; i < locale.length; i++) {
-                if (locale[i].equals(Locale.CHINA)) {
-                    sInstance = new HanziToPinyin(true);
-                    return sInstance;
-                }
-            }
-            Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");
-            sInstance = new HanziToPinyin(false);
-            return sInstance;
-        }
-    }
-
-    private Token getToken(char character) {
-        Token token = new Token();
-        final String letter = Character.toString(character);
-        token.source = letter;
-        int offset = -1;
-        int cmp;
-        if (character < 256) {
-            token.type = Token.LATIN;
-            token.target = letter;
-            return token;
-        } else if (character < FIRST_UNIHAN) {
-            token.type = Token.UNKNOWN;
-            token.target = letter;
-            return token;
-        } else {
-            cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN);
-            if (cmp < 0) {
-                token.type = Token.UNKNOWN;
-                token.target = letter;
-                return token;
-            } else if (cmp == 0) {
-                token.type = Token.PINYIN;
-                offset = 0;
-            } else {
-                cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN);
-                if (cmp > 0) {
-                    token.type = Token.UNKNOWN;
-                    token.target = letter;
-                    return token;
-                } else if (cmp == 0) {
-                    token.type = Token.PINYIN;
-                    offset = UNIHANS.length - 1;
-                }
-            }
-        }
-
-        token.type = Token.PINYIN;
-        if (offset < 0) {
-            int begin = 0;
-            int end = UNIHANS.length - 1;
-            while (begin <= end) {
-                offset = (begin + end) / 2;
-                final String unihan = Character.toString(UNIHANS[offset]);
-                cmp = COLLATOR.compare(letter, unihan);
-                if (cmp == 0) {
-                    break;
-                } else if (cmp > 0) {
-                    begin = offset + 1;
-                } else {
-                    end = offset - 1;
-                }
-            }
-        }
-        if (cmp < 0) {
-            offset--;
-        }
-        StringBuilder pinyin = new StringBuilder();
-        for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) {
-            pinyin.append((char)PINYINS[offset][j]);
-        }
-        token.target = pinyin.toString();
-        return token;
-    }
-
-    /**
-     * Convert the input to a array of tokens. The sequence of ASCII or Unknown
-     * characters without space will be put into a Token, One Hanzi character 
-     * which has pinyin will be treated as a Token.
-     * If these is no China collator, the empty token array is returned.
-     */
-    public ArrayList<Token> get(final String input) {
-        ArrayList<Token> tokens = new ArrayList<Token>();
-        if (!mHasChinaCollator || TextUtils.isEmpty(input)) {
-            // return empty tokens.
-            return tokens;
-        }
-        final int inputLength = input.length();
-        final StringBuilder sb = new StringBuilder();
-        int tokenType = Token.LATIN;
-        // Go through the input, create a new token when
-        // a. Token type changed
-        // b. Get the Pinyin of current charater.
-        // c. current character is space.
-        for (int i = 0; i < inputLength; i++) {
-            final char character = input.charAt(i);
-            if (character == ' ') {
-                if (sb.length() > 0) {
-                    addToken(sb, tokens, tokenType);
-                }
-            } else if (character < 256) {
-                if (tokenType != Token.LATIN && sb.length() > 0) {
-                    addToken(sb, tokens, tokenType);
-                }
-                tokenType = Token.LATIN;
-                sb.append(character);
-            } else if (character < FIRST_UNIHAN) {
-                if (tokenType != Token.UNKNOWN && sb.length() > 0) {
-                    addToken(sb, tokens, tokenType);
-                }
-                tokenType = Token.UNKNOWN;
-                sb.append(character);
-            } else {
-                Token t = getToken(character);
-                if (t.type == Token.PINYIN) {
-                    if (sb.length() > 0) {
-                        addToken(sb, tokens, tokenType);
-                    }
-                    tokens.add(t);
-                    tokenType = Token.PINYIN;
-                } else {
-                    if (tokenType != t.type && sb.length() > 0) {
-                        addToken(sb, tokens, tokenType);
-                    }
-                    tokenType = t.type;
-                    sb.append(character);
-                }
-            }
-        }
-        if (sb.length() > 0) {
-            addToken(sb, tokens, tokenType);
-        }
-        return tokens;
-    }
-
-    private void addToken(final StringBuilder sb, final ArrayList<Token> tokens,
-            final int tokenType) {
-        String str = sb.toString();
-        tokens.add(new Token(tokenType, str, str));
-        sb.setLength(0);
-    }
-
-}
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index f8d24a3..cc09927 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -177,7 +177,9 @@
 
     public void restoreHierarchyState(Bundle inState) {
         SparseArray<Parcelable> viewStates = inState.getSparseParcelableArray(VIEWS_TAG);
-        ((View) mMenuView).restoreHierarchyState(viewStates);
+        if (viewStates != null) {
+            ((View) mMenuView).restoreHierarchyState(viewStates);
+        }
     }
 
     private class MenuAdapter extends BaseAdapter {
diff --git a/core/tests/coretests/src/com/android/internal/util/HanziToPinyinTest.java b/core/tests/coretests/src/com/android/internal/util/HanziToPinyinTest.java
deleted file mode 100644
index 36dee70..0000000
--- a/core/tests/coretests/src/com/android/internal/util/HanziToPinyinTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.internal.util;
-
-import java.text.Collator;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Locale;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import com.android.internal.util.HanziToPinyin;
-import com.android.internal.util.HanziToPinyin.Token;
-
-import junit.framework.TestCase;
-
-public class HanziToPinyinTest extends TestCase {
-    private final static String ONE_HANZI = "\u675C";
-    private final static String TWO_HANZI = "\u675C\u9D51";
-    private final static String ASSIC = "test";
-    private final static String ONE_UNKNOWN = "\uFF71";
-    private final static String MISC = "test\u675C   Test with space\uFF71\uFF71\u675C";
-
-    @SmallTest
-    public void testGetToken() throws Exception {
-        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {
-            return;
-        }
-        ArrayList<Token> tokens = HanziToPinyin.getInstance().get(ONE_HANZI);
-        assertEquals(tokens.size(), 1);
-        assertEquals(tokens.get(0).type, Token.PINYIN);
-        assertTrue(tokens.get(0).target.equalsIgnoreCase("DU"));
-
-        tokens = HanziToPinyin.getInstance().get(TWO_HANZI);
-        assertEquals(tokens.size(), 2);
-        assertEquals(tokens.get(0).type, Token.PINYIN);
-        assertEquals(tokens.get(1).type, Token.PINYIN);
-        assertTrue(tokens.get(0).target.equalsIgnoreCase("DU"));
-        assertTrue(tokens.get(1).target.equalsIgnoreCase("JUAN"));
-
-        tokens = HanziToPinyin.getInstance().get(ASSIC);
-        assertEquals(tokens.size(), 1);
-        assertEquals(tokens.get(0).type, Token.LATIN);
-
-        tokens = HanziToPinyin.getInstance().get(ONE_UNKNOWN);
-        assertEquals(tokens.size(), 1);
-        assertEquals(tokens.get(0).type, Token.UNKNOWN);
-
-        tokens = HanziToPinyin.getInstance().get(MISC);
-        assertEquals(tokens.size(), 7);
-        assertEquals(tokens.get(0).type, Token.LATIN);
-        assertEquals(tokens.get(1).type, Token.PINYIN);
-        assertEquals(tokens.get(2).type, Token.LATIN);
-        assertEquals(tokens.get(3).type, Token.LATIN);
-        assertEquals(tokens.get(4).type, Token.LATIN);
-        assertEquals(tokens.get(5).type, Token.UNKNOWN);
-        assertEquals(tokens.get(6).type, Token.PINYIN);
-    }
-}
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index b5cc29c..b048469 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -537,15 +537,16 @@
     const float pathWidth = fmax(bounds.width(), 1.0f);
     const float pathHeight = fmax(bounds.height(), 1.0f);
 
-    if (pathWidth > mMaxTextureSize || pathHeight > mMaxTextureSize) {
+    const float offset = fmax(paint->getStrokeWidth(), 1.0f) * 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);
+
+    if (width > mMaxTextureSize || height > mMaxTextureSize) {
         LOGW("Shape %s too large to be rendered into a texture", mName);
         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) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 28add18..58f03a0 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1975,7 +1975,17 @@
     int64_t previousPausedDurationUs = 0;
     int64_t timestampUs = 0;
     int64_t cttsDeltaTimeUs = 0;
+    bool hasBFrames = false;
 
+#if 1
+    // XXX: Samsung's video encoder's output buffer timestamp
+    // is not correct. see bug 4724339
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("rw.media.record.hasb", value, NULL) &&
+        (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
+        hasBFrames = true;
+    }
+#endif
     if (mIsAudio) {
         prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
     } else {
@@ -2118,7 +2128,7 @@
 
         timestampUs -= previousPausedDurationUs;
         CHECK(timestampUs >= 0);
-        if (!mIsAudio) {
+        if (!mIsAudio && hasBFrames) {
             /*
              * Composition time: timestampUs
              * Decoding time: decodingTimeUs
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index f1da49d..ba3f344 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -35,16 +35,16 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.net.VpnConfig;
+
 import java.io.DataInputStream;
 import java.io.FileInputStream;
 
-public class ManageDialog extends Activity implements
+public class ManageDialog extends Activity implements Handler.Callback,
         DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
     private static final String TAG = "VpnManage";
 
-    private String mPackageName;
-    private String mInterfaceName;
-    private long mStartTime;
+    private VpnConfig mConfig;
 
     private IConnectivityManager mService;
 
@@ -53,28 +53,23 @@
     private TextView mDataTransmitted;
     private TextView mDataReceived;
 
-    private Updater mUpdater;
+    private Handler mHandler;
 
     @Override
     protected void onResume() {
         super.onResume();
         try {
-            Intent intent = getIntent();
-            // TODO: Move constants into VpnBuilder.
-            mPackageName = intent.getStringExtra("packageName");
-            mInterfaceName = intent.getStringExtra("interfaceName");
-            mStartTime = intent.getLongExtra("startTime", 0);
+            mConfig = getIntent().getParcelableExtra("config");
 
             mService = IConnectivityManager.Stub.asInterface(
                     ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
 
             PackageManager pm = getPackageManager();
-            ApplicationInfo app = pm.getApplicationInfo(mPackageName, 0);
+            ApplicationInfo app = pm.getApplicationInfo(mConfig.packageName, 0);
 
             View view = View.inflate(this, R.layout.manage, null);
-            String session = intent.getStringExtra("session");
-            if (session != null) {
-                ((TextView) view.findViewById(R.id.session)).setText(session);
+            if (mConfig.sessionName != null) {
+                ((TextView) view.findViewById(R.id.session)).setText(mConfig.sessionName);
             }
             mDuration = (TextView) view.findViewById(R.id.duration);
             mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
@@ -84,15 +79,21 @@
                     .setIcon(app.loadIcon(pm))
                     .setTitle(app.loadLabel(pm))
                     .setView(view)
-                    .setPositiveButton(R.string.configure, this)
                     .setNeutralButton(R.string.disconnect, this)
                     .setNegativeButton(android.R.string.cancel, this)
                     .create();
+
+            if (mConfig.configureActivity != null) {
+                mDialog.setButton(DialogInterface.BUTTON_POSITIVE,
+                        getText(R.string.configure), this);
+            }
             mDialog.setOnDismissListener(this);
             mDialog.show();
 
-            mUpdater = new Updater();
-            mUpdater.sendEmptyMessage(0);
+            if (mHandler == null) {
+                mHandler = new Handler(this);
+            }
+            mHandler.sendEmptyMessage(0);
         } catch (Exception e) {
             Log.e(TAG, "onResume", e);
             finish();
@@ -112,14 +113,15 @@
     public void onClick(DialogInterface dialog, int which) {
         try {
             if (which == AlertDialog.BUTTON_POSITIVE) {
-                Intent intent = new Intent(Intent.ACTION_MAIN);
-                intent.setPackage(mPackageName);
+                Intent intent = new Intent();
+                intent.setClassName(mConfig.packageName, mConfig.configureActivity);
                 startActivity(intent);
             } else if (which == AlertDialog.BUTTON_NEUTRAL) {
-                mService.prepareVpn(mPackageName);
+                mService.prepareVpn("");
             }
         } catch (Exception e) {
             Log.e(TAG, "onClick", e);
+            finish();
         }
     }
 
@@ -128,30 +130,30 @@
         finish();
     }
 
-    private class Updater extends Handler {
-        public void handleMessage(Message message) {
-            removeMessages(0);
+    @Override
+    public boolean handleMessage(Message message) {
+        mHandler.removeMessages(0);
 
-            if (mDialog.isShowing()) {
-                if (mStartTime != 0) {
-                    long seconds = (SystemClock.elapsedRealtime() - mStartTime) / 1000;
-                    mDuration.setText(String.format("%02d:%02d:%02d",
-                            seconds / 3600, seconds / 60 % 60, seconds % 60));
-                }
-
-                String[] numbers = getStatistics();
-                if (numbers != null) {
-                    // [1] and [2] are received data in bytes and packets.
-                    mDataReceived.setText(getString(R.string.data_value_format,
-                            numbers[1], numbers[2]));
-
-                    // [9] and [10] are transmitted data in bytes and packets.
-                    mDataTransmitted.setText(getString(R.string.data_value_format,
-                            numbers[9], numbers[10]));
-                }
-                sendEmptyMessageDelayed(0, 1000);
+        if (mDialog.isShowing()) {
+            if (mConfig.startTime != 0) {
+                long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000;
+                mDuration.setText(String.format("%02d:%02d:%02d",
+                        seconds / 3600, seconds / 60 % 60, seconds % 60));
             }
+
+            String[] numbers = getStatistics();
+            if (numbers != null) {
+                // [1] and [2] are received data in bytes and packets.
+                mDataReceived.setText(getString(R.string.data_value_format,
+                        numbers[1], numbers[2]));
+
+                // [9] and [10] are transmitted data in bytes and packets.
+                mDataTransmitted.setText(getString(R.string.data_value_format,
+                        numbers[9], numbers[10]));
+            }
+            mHandler.sendEmptyMessageDelayed(0, 1000);
         }
+        return true;
     }
 
     private String[] getStatistics() {
@@ -159,7 +161,7 @@
         try {
             // See dev_seq_printf_stats() in net/core/dev.c.
             in = new DataInputStream(new FileInputStream("/proc/net/dev"));
-            String prefix = mInterfaceName + ':';
+            String prefix = mConfig.interfaceName + ':';
 
             while (true) {
                 String line = in.readLine().trim();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f1098a8..4ec71c1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1933,6 +1933,9 @@
             int debugFlags = 0;
             if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+                // Also turn on CheckJNI for debuggable apps. It's quite
+                // awkward to turn on otherwise.
+                debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
             }
             // Run the app in safe mode if its manifest requests so or the
             // system is booted in safe mode.
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 372ba85..035a6679 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -18,7 +18,6 @@
 
 import android.app.Notification;
 import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -64,29 +63,40 @@
      * @return The name of the current prepared package.
      */
     public synchronized String prepare(String packageName) {
-
-        // TODO: Check if the caller is VpnDialogs.
-
+        // Return the current prepared package if the new one is null.
         if (packageName == null) {
             return mPackageName;
         }
 
-        // Check the permission of the given application.
+        // Check the permission of the caller.
         PackageManager pm = mContext.getPackageManager();
-        if (pm.checkPermission(VPN, packageName) != PackageManager.PERMISSION_GRANTED) {
+        VpnConfig.enforceCallingPackage(pm.getNameForUid(Binder.getCallingUid()));
+
+        // Check the permission of the given package.
+        if (packageName.isEmpty()) {
+            packageName = null;
+        } else if (pm.checkPermission(VPN, packageName) != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException(packageName + " does not have " + VPN);
         }
 
         // Reset the interface and hide the notification.
         if (mInterfaceName != null) {
             nativeReset(mInterfaceName);
-            mInterfaceName = null;
+            mCallback.restore();
             hideNotification();
-            // TODO: Send out a broadcast.
+            mInterfaceName = null;
         }
 
+        // Notify the package being revoked.
+        if (mPackageName != null) {
+            Intent intent = new Intent(VpnConfig.ACTION_VPN_REVOKED);
+            intent.setPackage(mPackageName);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+            mContext.sendBroadcast(intent);
+        }
+
+        Log.i(TAG, "Switched from " + mPackageName + " to " + packageName);
         mPackageName = packageName;
-        Log.i(TAG, "Prepared for " + packageName);
         return mPackageName;
     }
 
@@ -118,10 +128,10 @@
         try {
             app = pm.getApplicationInfo(mPackageName, 0);
         } catch (Exception e) {
-            throw new SecurityException("Not prepared");
+            return null;
         }
         if (Binder.getCallingUid() != app.uid) {
-            throw new SecurityException("Not prepared");
+            return null;
         }
 
         // Create and configure the interface.
@@ -148,7 +158,9 @@
         String dnsServers = (config.dnsServers == null) ? "" : config.dnsServers.trim();
         mCallback.override(dnsServers.isEmpty() ? null : dnsServers.split(" "));
 
-        showNotification(pm, app, config.sessionName);
+        config.packageName = mPackageName;
+        config.interfaceName = mInterfaceName;
+        showNotification(pm, app, config);
         return descriptor;
     }
 
@@ -169,7 +181,7 @@
         }
     }
 
-    private void showNotification(PackageManager pm, ApplicationInfo app, String sessionName) {
+    private void showNotification(PackageManager pm, ApplicationInfo app, VpnConfig config) {
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
@@ -190,20 +202,9 @@
             // Load the label.
             String label = app.loadLabel(pm).toString();
 
-            // Build the intent.
-            // TODO: move these into VpnBuilder.
-            Intent intent = new Intent();
-            intent.setClassName("com.android.vpndialogs",
-                    "com.android.vpndialogs.ManageDialog");
-            intent.putExtra("packageName", mPackageName);
-            intent.putExtra("interfaceName", mInterfaceName);
-            intent.putExtra("session", sessionName);
-            intent.putExtra("startTime", android.os.SystemClock.elapsedRealtime());
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
             // Build the notification.
-            String text = (sessionName == null) ? mContext.getString(R.string.vpn_text) :
-                    mContext.getString(R.string.vpn_text_long, sessionName);
+            String text = (config.sessionName == null) ? mContext.getString(R.string.vpn_text) :
+                    mContext.getString(R.string.vpn_text_long, config.sessionName);
             long identity = Binder.clearCallingIdentity();
             Notification notification = new Notification.Builder(mContext)
                     .setSmallIcon(R.drawable.vpn_connected)
@@ -211,7 +212,7 @@
                     .setTicker(mContext.getString(R.string.vpn_ticker, label))
                     .setContentTitle(mContext.getString(R.string.vpn_title, label))
                     .setContentText(text)
-                    .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0))
+                    .setContentIntent(VpnConfig.getIntentForNotification(mContext, config))
                     .setDefaults(Notification.DEFAULT_ALL)
                     .setOngoing(true)
                     .getNotification();
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index e1fbe1c..5a9dae9 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
 import com.android.internal.app.IMediaContainerService;
@@ -7048,7 +7049,8 @@
             final String packageName, String className, int newState, final int flags) {
         if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
               || newState == COMPONENT_ENABLED_STATE_ENABLED
-              || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
+              || newState == COMPONENT_ENABLED_STATE_DISABLED
+              || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
             throw new IllegalArgumentException("Invalid new component state: "
                     + newState);
         }
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 2720bf8..5ed7988 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
 import com.android.internal.util.FastXmlSerializer;
@@ -1912,6 +1913,7 @@
             return false;
         }
         if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
+                || packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
                 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
                         && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
             return false;
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 3e7ca08..d5dcd4e 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -31,6 +31,15 @@
         android:hardwareAccelerated="true">
 
         <activity
+                android:name="SmallCircleActivity"
+                android:label="_SmallCircle">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="ClearActivity"
                 android:label="_Clear">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
new file mode 100644
index 0000000..8c02539
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
@@ -0,0 +1,70 @@
+/*
+ * 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.Path;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.LinearLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class SmallCircleActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+
+        View view = new PathView(this);
+        layout.addView(view, new LinearLayout.LayoutParams(PathView.SIZE, PathView.SIZE));
+        view = new PathView(this);
+        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        layout.addView(view, new LinearLayout.LayoutParams(PathView.SIZE, PathView.SIZE));
+
+        setContentView(layout);
+    }
+
+    static class PathView extends View {
+        private static final int SIZE = 37;
+        private final Paint mPaint;
+        private final Path mPath;
+
+        PathView(Context c) {
+            super(c);
+
+            mPath = new Path();
+            mPath.addCircle(SIZE * 0.5f, SIZE * 0.5f, SIZE * 0.275f, Path.Direction.CW);
+            mPath.addCircle(SIZE * 0.5f, SIZE * 0.5f, SIZE * 0.225f, Path.Direction.CCW);
+            
+            mPaint = new Paint();
+            mPaint.setAntiAlias(true);
+            mPaint.setColor(0xffffffff);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            canvas.drawPath(mPath, mPaint);
+        }
+    }
+}