Merge "Fix determining find on page overlap" into ics-mr1
diff --git a/api/current.txt b/api/current.txt
index cc7f0798..d83659f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4145,6 +4145,7 @@
     ctor public AppWidgetHostView(android.content.Context, int, int);
     method public int getAppWidgetId();
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo();
+    method public static android.graphics.Rect getDefaultPaddingForWidget(android.content.Context, android.content.ComponentName, android.graphics.Rect);
     method protected android.view.View getDefaultView();
     method protected android.view.View getErrorView();
     method protected void prepareView(android.view.View);
@@ -4474,10 +4475,12 @@
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public int describeContents();
+    method public boolean fetchUuidsWithSdp();
     method public java.lang.String getAddress();
     method public android.bluetooth.BluetoothClass getBluetoothClass();
     method public int getBondState();
     method public java.lang.String getName();
+    method public android.os.ParcelUuid[] getUuids();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final java.lang.String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
     field public static final java.lang.String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
@@ -4486,6 +4489,7 @@
     field public static final java.lang.String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
     field public static final java.lang.String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
     field public static final java.lang.String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
+    field public static final java.lang.String ACTION_UUID = "android.bluetooth.device.action.UUID";
     field public static final int BOND_BONDED = 12; // 0xc
     field public static final int BOND_BONDING = 11; // 0xb
     field public static final int BOND_NONE = 10; // 0xa
@@ -4497,6 +4501,7 @@
     field public static final java.lang.String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
     field public static final java.lang.String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
     field public static final java.lang.String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
+    field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
   }
 
   public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
@@ -8792,6 +8797,7 @@
     method public long getTimestamp();
     method public void getTransformMatrix(float[]);
     method public void release();
+    method public void setDefaultBufferSize(int, int);
     method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
     method public void updateTexImage();
   }
@@ -16606,6 +16612,10 @@
     field public static final java.lang.String PHOTO_FILE_ID = "data14";
   }
 
+  public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
   protected static abstract interface ContactsContract.ContactsColumns {
     field public static final java.lang.String DISPLAY_NAME = "display_name";
     field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number";
@@ -16863,6 +16873,10 @@
     field public static final java.lang.String DATA_ID = "data_id";
   }
 
+  public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
   protected static abstract interface ContactsContract.RawContactsColumns {
     field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
     field public static final java.lang.String CONTACT_ID = "contact_id";
@@ -16926,6 +16940,56 @@
     field public static final android.net.Uri PROFILE_CONTENT_URI;
   }
 
+  public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String PHOTO = "photo";
+  }
+
+  protected static abstract interface ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
+    field public static final java.lang.String PHOTO_URI = "photo_uri";
+    field public static final java.lang.String SORT_INDEX = "sort_index";
+    field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id";
+    field public static final java.lang.String SYNC1 = "stream_item_photo_sync1";
+    field public static final java.lang.String SYNC2 = "stream_item_photo_sync2";
+    field public static final java.lang.String SYNC3 = "stream_item_photo_sync3";
+    field public static final java.lang.String SYNC4 = "stream_item_photo_sync4";
+  }
+
+  public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
+    field public static final android.net.Uri CONTENT_LIMIT_URI;
+    field public static final android.net.Uri CONTENT_PHOTO_URI;
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String MAX_ITEMS = "max_items";
+  }
+
+  public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
+  }
+
+  protected static abstract interface ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String COMMENTS = "comments";
+    field public static final java.lang.String CONTACT_ID = "contact_id";
+    field public static final java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
+    field public static final java.lang.String DATA_SET = "data_set";
+    field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+    field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
+    field public static final java.lang.String RES_ICON = "icon";
+    field public static final java.lang.String RES_LABEL = "label";
+    field public static final java.lang.String RES_PACKAGE = "res_package";
+    field public static final java.lang.String SYNC1 = "stream_item_sync1";
+    field public static final java.lang.String SYNC2 = "stream_item_sync2";
+    field public static final java.lang.String SYNC3 = "stream_item_sync3";
+    field public static final java.lang.String SYNC4 = "stream_item_sync4";
+    field public static final java.lang.String TEXT = "text";
+    field public static final java.lang.String TIMESTAMP = "timestamp";
+  }
+
   protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
     field public static final java.lang.String ACCOUNT_NAME = "account_name";
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
@@ -17363,6 +17427,7 @@
     field public static final java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
     field public static final java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
     field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
+    field public static final java.lang.String MESSAGING_APP_NOTIFICATIONS = "messaging_app_notifications";
     field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
     field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
     field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 4f72289..7c03a2f 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -109,6 +109,10 @@
             runStartService();
         } else if (op.equals("force-stop")) {
             runForceStop();
+        } else if (op.equals("kill")) {
+            runKill();
+        } else if (op.equals("kill-all")) {
+            runKillAll();
         } else if (op.equals("instrument")) {
             runInstrument();
         } else if (op.equals("broadcast")) {
@@ -484,6 +488,14 @@
         mAm.forceStopPackage(nextArgRequired());
     }
 
+    private void runKill() throws Exception {
+        mAm.killBackgroundProcesses(nextArgRequired());
+    }
+
+    private void runKillAll() throws Exception {
+        mAm.killAllBackgroundProcesses();
+    }
+
     private void sendBroadcast() throws Exception {
         Intent intent = makeIntent();
         IntentReceiver receiver = new IntentReceiver();
@@ -1179,6 +1191,8 @@
                 "               [--R COUNT] [-S] <INTENT>\n" +
                 "       am startservice <INTENT>\n" +
                 "       am force-stop <PACKAGE>\n" +
+                "       am kill <PACKAGE>\n" +
+                "       am kill-all\n" +
                 "       am broadcast <INTENT>\n" +
                 "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
                 "               [--no-window-animation] <COMPONENT>\n" +
@@ -1202,6 +1216,12 @@
                 "\n" +
                 "am force-stop: force stop everything associated with <PACKAGE>.\n" +
                 "\n" +
+                "am kill: Kill all processes associated with <PACKAGE>.  Only kills.\n" +
+                "  processes that are safe to kill -- that is, will not impact the user\n" +
+                "  experience.\n" +
+                "\n" +
+                "am kill-all: Kill all background processes.\n" +
+                "\n" +
                 "am broadcast: send a broadcast Intent.\n" +
                 "\n" +
                 "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 2378345..bd430d1 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -360,7 +360,7 @@
         service->create(getpid(), client, 0);
 
     if (player != NULL && player->setDataSource(source) == NO_ERROR) {
-        player->setVideoSurface(surface);
+        player->setVideoSurfaceTexture(surface->getSurfaceTexture());
         player->start();
 
         client->waitForEOS();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b4471f0..7994d7c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1092,6 +1092,13 @@
             reply.writeNoException();
             return true;
         }
+
+        case KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            killAllBackgroundProcesses();
+            reply.writeNoException();
+            return true;
+        }
         
         case FORCE_STOP_PACKAGE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
@@ -2906,7 +2913,7 @@
         data.recycle();
         reply.recycle();
     }
-    
+
     public void killBackgroundProcesses(String packageName) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2917,7 +2924,17 @@
         data.recycle();
         reply.recycle();
     }
-    
+
+    public void killAllBackgroundProcesses() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     public void forceStopPackage(String packageName) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 00fe953..a4714ca 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3832,11 +3832,16 @@
          * Initialize the default http proxy in this process for the reasons we set the time zone.
          */
         IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
-        try {
-            ProxyProperties proxyProperties = service.getProxy();
-            Proxy.setHttpProxySystemProperty(proxyProperties);
-        } catch (RemoteException e) {}
+        if (b != null) {
+            // In pre-boot mode (doing initial launch to collect password), not
+            // all system is up.  This includes the connectivity service, so don't
+            // crash if we can't get it.
+            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
+            try {
+                ProxyProperties proxyProperties = service.getProxy();
+                Proxy.setHttpProxySystemProperty(proxyProperties);
+            } catch (RemoteException e) {}
+        }
 
         if (data.instrumentationName != null) {
             ContextImpl appContext = new ContextImpl();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 26813bf..5222d37 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -234,6 +234,7 @@
     public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
     
     public void killBackgroundProcesses(final String packageName) throws RemoteException;
+    public void killAllBackgroundProcesses() throws RemoteException;
     public void forceStopPackage(final String packageName) throws RemoteException;
     
     // Note: probably don't want to allow applications access to these.
@@ -605,4 +606,5 @@
     int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136;
     int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137;
     int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138;
+    int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139;
 }
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 761c7eb..61a9dce 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -26,6 +26,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.Rect;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -41,8 +42,8 @@
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
-import android.widget.TextView;
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
+import android.widget.TextView;
 
 /**
  * Provides the glue to show AppWidget views. This class offers automatic animation
@@ -106,7 +107,9 @@
     }
 
     /**
-     * Set the AppWidget that will be displayed by this view.
+     * Set the AppWidget that will be displayed by this view. This method also adds default padding
+     * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
+     * and can be overridden in order to add custom padding.
      */
     public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) {
         mAppWidgetId = appWidgetId;
@@ -116,49 +119,57 @@
         // a widget, eg. for some widgets in safe mode.
         if (info != null) {
             // We add padding to the AppWidgetHostView if necessary
-            Padding padding = getPaddingForWidget(info.provider);
+            Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null);
             setPadding(padding.left, padding.top, padding.right, padding.bottom);
         }
     }
 
-    private static class Padding {
-        int left = 0;
-        int right = 0;
-        int top = 0;
-        int bottom = 0;
-    }
-
     /**
      * As of ICE_CREAM_SANDWICH we are automatically adding padding to widgets targeting
      * ICE_CREAM_SANDWICH and higher. The new widget design guidelines strongly recommend
      * that widget developers do not add extra padding to their widgets. This will help
      * achieve consistency among widgets.
+     *
+     * Note: this method is only needed by developers of AppWidgetHosts. The method is provided in
+     * order for the AppWidgetHost to account for the automatic padding when computing the number
+     * of cells to allocate to a particular widget.
+     *
+     * @param context the current context
+     * @param component the component name of the widget
+     * @param padding Rect in which to place the output, if null, a new Rect will be allocated and
+     *                returned
+     * @return default padding for this widget
      */
-    private Padding getPaddingForWidget(ComponentName component) {
-        PackageManager packageManager = mContext.getPackageManager();
-        Padding p = new Padding();
+    public static Rect getDefaultPaddingForWidget(Context context, ComponentName component,
+            Rect padding) {
+        PackageManager packageManager = context.getPackageManager();
         ApplicationInfo appInfo;
 
+        if (padding == null) {
+            padding = new Rect(0, 0, 0, 0);
+        } else {
+            padding.set(0, 0, 0, 0);
+        }
+
         try {
             appInfo = packageManager.getApplicationInfo(component.getPackageName(), 0);
-        } catch (Exception e) {
+        } catch (NameNotFoundException e) {
             // if we can't find the package, return 0 padding
-            return p;
+            return padding;
         }
 
         if (appInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
-            Resources r = getResources();
-            p.left = r.getDimensionPixelSize(com.android.internal.
+            Resources r = context.getResources();
+            padding.left = r.getDimensionPixelSize(com.android.internal.
                     R.dimen.default_app_widget_padding_left);
-            p.right = r.getDimensionPixelSize(com.android.internal.
+            padding.right = r.getDimensionPixelSize(com.android.internal.
                     R.dimen.default_app_widget_padding_right);
-            p.top = r.getDimensionPixelSize(com.android.internal.
+            padding.top = r.getDimensionPixelSize(com.android.internal.
                     R.dimen.default_app_widget_padding_top);
-            p.bottom = r.getDimensionPixelSize(com.android.internal.
+            padding.bottom = r.getDimensionPixelSize(com.android.internal.
                     R.dimen.default_app_widget_padding_bottom);
         }
-
-        return p;
+        return padding;
     }
 
     public int getAppWidgetId() {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 4cb8220..0306521 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -247,13 +247,12 @@
      * has been fetched. This intent is sent only when the UUIDs of the remote
      * device are requested to be fetched using Service Discovery Protocol
      * <p> Always contains the extra field {@link #EXTRA_DEVICE}
-     * <p> Always contains the extra filed {@link #EXTRA_UUID}
+     * <p> Always contains the extra field {@link #EXTRA_UUID}
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_UUID =
-            "android.bleutooth.device.action.UUID";
+            "android.bluetooth.device.action.UUID";
 
     /**
      * Broadcast Action: Indicates a failure to retrieve the name of a remote
@@ -451,7 +450,6 @@
      * Used as an extra field in {@link #ACTION_UUID} intents,
      * Contains the {@link android.os.ParcelUuid}s of the remote device which
      * is a parcelable version of {@link UUID}.
-     * @hide
      */
     public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
 
@@ -770,7 +768,18 @@
         return false;
     }
 
-    /** @hide */
+    /**
+     * Returns the supported features (UUIDs) of the remote device.
+     *
+     * <p>This method does not start a service discovery procedure to retrieve the UUIDs
+     * from the remote device. Instead, the local cached copy of the service
+     * UUIDs are returned.
+     * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
+     *
+     * @return the supported features (UUIDs) of the remote device,
+     *         or null on error
+     */
      public ParcelUuid[] getUuids() {
         try {
             return sService.getRemoteUuids(mAddress);
@@ -779,18 +788,19 @@
     }
 
      /**
-      *  Perform a SDP query on the remote device to get the UUIDs
-      *  supported. This API is asynchronous and an Intent is sent,
-      *  with the UUIDs supported by the remote end. If there is an error
-      *  in getting the SDP records or if the process takes a long time,
-      *  an Intent is sent with the UUIDs that is currently present in the
-      *  cache. Clients should use the {@link #getUuids} to get UUIDs
-      *  is SDP is not to be performed.
+      * Perform a service discovery on the remote device to get the UUIDs supported.
       *
-      *  @return False if the sanity check fails, True if the process
+      * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
+      * with the UUIDs supported by the remote end. If there is an error
+      * in getting the SDP records or if the process takes a long time,
+      * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently
+      * present in the cache. Clients should use the {@link #getUuids} to get UUIDs
+      * if service discovery is not to be performed.
+      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
+      *
+      * @return False if the sanity check fails, True if the process
       *               of initiating an ACL connection to the remote device
       *               was started.
-      *  @hide
       */
      public boolean fetchUuidsWithSdp() {
         try {
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 5c6ef1a..3605652 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -165,6 +165,17 @@
         dest.writeLongArray(operations);
     }
 
+    @Override
+    public NetworkStats clone() {
+        final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
+        NetworkStats.Entry entry = null;
+        for (int i = 0; i < size; i++) {
+            entry = getValues(i, entry);
+            clone.addValues(entry);
+        }
+        return clone;
+    }
+
     // @VisibleForTesting
     public NetworkStats addIfaceValues(
             String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
@@ -455,7 +466,7 @@
     public NetworkStats subtract(NetworkStats value) throws NonMonotonicException {
         final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime;
         if (deltaRealtime < 0) {
-            throw new IllegalArgumentException("found non-monotonic realtime");
+            throw new NonMonotonicException(this, value);
         }
 
         // result will have our rows, and elapsed time between snapshots
@@ -575,7 +586,8 @@
         pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
         for (int i = 0; i < size; i++) {
             pw.print(prefix);
-            pw.print("  iface="); pw.print(iface[i]);
+            pw.print("  ["); pw.print(i); pw.print("]");
+            pw.print(" iface="); pw.print(iface[i]);
             pw.print(" uid="); pw.print(uid[i]);
             pw.print(" set="); pw.print(setToString(set[i]));
             pw.print(" tag="); pw.print(tagToString(tag[i]));
@@ -638,6 +650,10 @@
         public final int leftIndex;
         public final int rightIndex;
 
+        public NonMonotonicException(NetworkStats left, NetworkStats right) {
+            this(left, -1, right, -1);
+        }
+
         public NonMonotonicException(
                 NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) {
             this.left = checkNotNull(left, "missing left");
diff --git a/core/java/android/net/wimax/WimaxManagerConstants.java b/core/java/android/net/wimax/WimaxManagerConstants.java
new file mode 100644
index 0000000..b4aaf5b
--- /dev/null
+++ b/core/java/android/net/wimax/WimaxManagerConstants.java
@@ -0,0 +1,104 @@
+package android.net.wimax;
+
+/**
+ * {@hide}
+ */
+public class WimaxManagerConstants
+{
+
+    /**
+     * Used by android.net.wimax.WimaxManager for handling management of
+     * Wimax access.
+     */
+    public static final String WIMAX_SERVICE = "WiMax";
+
+    /**
+     * Broadcast intent action indicating that Wimax has been enabled, disabled,
+     * enabling, disabling, or unknown. One extra provides this state as an int.
+     * Another extra provides the previous state, if available.
+     */
+    public static final String NET_4G_STATE_CHANGED_ACTION =
+        "android.net.fourG.NET_4G_STATE_CHANGED";
+
+    /**
+     * The lookup key for an int that indicates whether Wimax is enabled,
+     * disabled, enabling, disabling, or unknown.
+     */
+    public static final String EXTRA_WIMAX_STATUS = "wimax_status";
+
+    /**
+     * Broadcast intent action indicating that Wimax state has been changed
+     * state could be scanning, connecting, connected, disconnecting, disconnected
+     * initializing, initialized, unknown and ready. One extra provides this state as an int.
+     * Another extra provides the previous state, if available.
+     */
+    public static final String  WIMAX_NETWORK_STATE_CHANGED_ACTION =
+        "android.net.fourG.wimax.WIMAX_NETWORK_STATE_CHANGED";
+
+    /**
+     * Broadcast intent action indicating that Wimax signal level has been changed.
+     * Level varies from 0 to 3.
+     */
+    public static final String SIGNAL_LEVEL_CHANGED_ACTION =
+        "android.net.wimax.SIGNAL_LEVEL_CHANGED";
+
+    /**
+     * The lookup key for an int that indicates whether Wimax state is
+     * scanning, connecting, connected, disconnecting, disconnected
+     * initializing, initialized, unknown and ready.
+     */
+    public static final String EXTRA_WIMAX_STATE = "WimaxState";
+    public static final String EXTRA_4G_STATE = "4g_state";
+    public static final String EXTRA_WIMAX_STATE_INT = "WimaxStateInt";
+    /**
+     * The lookup key for an int that indicates whether state of Wimax
+     * is idle.
+     */
+    public static final String EXTRA_WIMAX_STATE_DETAIL = "WimaxStateDetail";
+
+    /**
+     * The lookup key for an int that indicates Wimax signal level.
+     */
+    public static final String EXTRA_NEW_SIGNAL_LEVEL = "newSignalLevel";
+
+    /**
+     * Indicatates Wimax is disabled.
+     */
+    public static final int NET_4G_STATE_DISABLED = 1;
+
+    /**
+     * Indicatates Wimax is enabled.
+     */
+    public static final int NET_4G_STATE_ENABLED = 3;
+
+    /**
+     * Indicatates Wimax status is known.
+     */
+    public static final int NET_4G_STATE_UNKNOWN = 4;
+
+    /**
+     * Indicatates Wimax is in idle state.
+     */
+    public static final int WIMAX_IDLE = 6;
+
+    /**
+     * Indicatates Wimax is being deregistered.
+     */
+    public static final int WIMAX_DEREGISTRATION = 8;
+
+    /**
+     * Indicatates wimax state is unknown.
+     */
+    public static final int WIMAX_STATE_UNKNOWN = 0;
+
+    /**
+     * Indicatates wimax state is connected.
+     */
+    public static final int WIMAX_STATE_CONNECTED = 7;
+
+    /**
+     * Indicatates wimax state is disconnected.
+     */
+    public static final int WIMAX_STATE_DISCONNECTED = 9;
+
+}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index ff28596..821b6df 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1673,7 +1673,6 @@
          * Querying for social stream data requires android.permission.READ_SOCIAL_STREAM
          * permission.
          * </p>
-         * @hide
          */
         public static final class StreamItems implements StreamItemsColumns {
             /**
@@ -2736,7 +2735,6 @@
          * inserting or updating social stream items requires android.permission.WRITE_SOCIAL_STREAM
          * permission.
          * </p>
-         * @hide
          */
         public static final class StreamItems implements BaseColumns, StreamItemsColumns {
             /**
@@ -3149,7 +3147,6 @@
      * </pre>
      * </dd>
      * </dl>
-     * @hide
      */
     public static final class StreamItems implements BaseColumns, StreamItemsColumns {
         /**
@@ -3247,7 +3244,6 @@
      * Columns in the StreamItems table.
      *
      * @see ContactsContract.StreamItems
-     * @hide
      */
     protected interface StreamItemsColumns {
         /**
@@ -3538,7 +3534,6 @@
      * <pre>
      * </dd>
      * </dl>
-     * @hide
      */
     public static final class StreamItemPhotos implements BaseColumns, StreamItemPhotosColumns {
         /**
@@ -3566,7 +3561,6 @@
      * Columns in the StreamItemPhotos table.
      *
      * @see ContactsContract.StreamItemPhotos
-     * @hide
      */
     protected interface StreamItemPhotosColumns {
         /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a0652f7..769776e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1183,6 +1183,10 @@
         public static final String RADIO_WIFI = "wifi";
 
         /**
+         * {@hide}
+         */
+        public static final String RADIO_WIMAX = "wimax";
+        /**
          * Constant for use in AIRPLANE_MODE_RADIOS to specify Cellular radio.
          */
         public static final String RADIO_CELL = "cell";
@@ -2899,6 +2903,11 @@
          */
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
                 "wifi_networks_available_notification_on";
+        /**
+         * {@hide}
+         */
+        public static final String WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON =
+                "wimax_networks_available_notification_on";
 
         /**
          * Delay (in seconds) before repeating the Wi-Fi networks available notification.
@@ -4068,6 +4077,13 @@
                 "contacts_preauth_uri_expiration";
 
         /**
+         * Whether the Messaging app posts notifications.
+         * 0=disabled. 1=enabled.
+         */
+        public static final String MESSAGING_APP_NOTIFICATIONS = "messaging_app_notifications";
+
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -4104,7 +4120,8 @@
             MOUNT_UMS_NOTIFY_ENABLED,
             UI_NIGHT_MODE,
             LOCK_SCREEN_OWNER_INFO,
-            LOCK_SCREEN_OWNER_INFO_ENABLED
+            LOCK_SCREEN_OWNER_INFO_ENABLED,
+            MESSAGING_APP_NOTIFICATIONS
         };
 
         /**
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 0e6d07d..8eb9da1 100755
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1838,5 +1838,15 @@
         public static final String EXTRA_PLMN       = "plmn";
         public static final String EXTRA_SHOW_SPN   = "showSpn";
         public static final String EXTRA_SPN        = "spn";
+
+        /**
+         * Activity Action: Shows a dialog to turn off Messaging app notification.
+         * <p>Input: Nothing.
+         * <p>Output: Nothing.
+         */
+        @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+        public static final String ACTION_MESSAGING_APP_NOTIFICATIONS =
+            "android.provider.Telephony.MESSAGING_APP_NOTIFICATIONS";
+
     }
 }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 5ee1b8a..8aafc3d 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -16,14 +16,9 @@
 
 package android.webkit;
 
-import com.android.internal.widget.EditableInputConnection;
-
 import android.content.Context;
-import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.ColorFilter;
 import android.graphics.Paint;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
@@ -60,12 +55,12 @@
 import android.widget.AutoCompleteTextView;
 import android.widget.TextView;
 
+import junit.framework.Assert;
+
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 
-import junit.framework.Assert;
-
 /**
  * WebTextView is a specialized version of EditText used by WebView
  * to overlay html textfields (and textareas) to use our standard
@@ -926,18 +921,23 @@
      */
     /* package */ void setRect(int x, int y, int width, int height) {
         LayoutParams lp = (LayoutParams) getLayoutParams();
+        boolean needsUpdate = false;
         if (null == lp) {
             lp = new LayoutParams(width, height, x, y);
         } else {
-            lp.x = x;
-            lp.y = y;
-            lp.width = width;
-            lp.height = height;
+            if ((lp.x != x) || (lp.y != y) || (lp.width != width)
+                    || (lp.height != height)) {
+                needsUpdate = true;
+                lp.x = x;
+                lp.y = y;
+                lp.width = width;
+                lp.height = height;
+            }
         }
         if (getParent() == null) {
             // Insert the view so that it's drawn first (at index 0)
             mWebView.addView(this, 0, lp);
-        } else {
+        } else if (needsUpdate) {
             setLayoutParams(lp);
         }
         // Set up a measure spec so a layout can always be recreated.
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 5ab99dc..1a1b8d0 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -741,9 +741,16 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMinWidth, mMaxWidth);
-        final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMinHeight, mMaxHeight);
+        // Try greedily to fit the max width and height.
+        final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMaxWidth);
+        final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight);
         super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
+        // Flag if we are measured with width or height less than the respective min.
+        final int desiredWidth = Math.max(mMinWidth, getMeasuredWidth());
+        final int desiredHeight = Math.max(mMinHeight, getMeasuredHeight());
+        final int widthSize = resolveSizeAndState(desiredWidth, newWidthMeasureSpec, 0);
+        final int heightSize = resolveSizeAndState(desiredHeight, newHeightMeasureSpec, 0);
+        setMeasuredDimension(widthSize, heightSize);
     }
 
     @Override
@@ -1357,23 +1364,19 @@
      * Makes a measure spec that tries greedily to use the max value.
      *
      * @param measureSpec The measure spec.
-     * @param maxValue The max value for the size.
+     * @param maxSize The max value for the size.
      * @return A measure spec greedily imposing the max size.
      */
-    private int makeMeasureSpec(int measureSpec, int minValue, int maxValue) {
+    private int makeMeasureSpec(int measureSpec, int maxSize) {
         final int size = MeasureSpec.getSize(measureSpec);
-        if (size < minValue) {
-            throw new IllegalArgumentException("Available space is less than min size: "
-                    +  size + " < " + minValue);
-        }
         final int mode = MeasureSpec.getMode(measureSpec);
         switch (mode) {
             case MeasureSpec.EXACTLY:
                 return measureSpec;
             case MeasureSpec.AT_MOST:
-                return MeasureSpec.makeMeasureSpec(Math.min(size, maxValue), MeasureSpec.EXACTLY);
+                return MeasureSpec.makeMeasureSpec(Math.min(size, maxSize), MeasureSpec.EXACTLY);
             case MeasureSpec.UNSPECIFIED:
-                return MeasureSpec.makeMeasureSpec(maxValue, MeasureSpec.EXACTLY);
+                return MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.EXACTLY);
             default:
                 throw new IllegalArgumentException("Unknown measure mode: " + mode);
         }
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index e929e7d..87c3e9b 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -82,6 +82,8 @@
     }
 
     private void setLocale(Locale locale) {
+        closeSession();
+
         final TextServicesManager textServicesManager = (TextServicesManager)
                 mTextView.getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
         if (!textServicesManager.isSpellCheckerEnabled()) {
@@ -104,12 +106,6 @@
         // Change SpellParsers' wordIterator locale
         mWordIterator = new WordIterator(locale);
 
-        // Stop all SpellParsers
-        final int length = mSpellParsers.length;
-        for (int i = 0; i < length; i++) {
-            mSpellParsers[i].finish();
-        }
-
         // Remove existing misspelled SuggestionSpans
         mTextView.removeMisspelledSpans((Editable) mTextView.getText());
 
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 27d44bf..ec3790e 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -68,6 +68,7 @@
     int mDropDownWidth;
 
     private int mGravity;
+    private boolean mDisableChildrenWhenDisabled;
 
     private Rect mTempRect = new Rect();
 
@@ -186,6 +187,9 @@
 
         mPopup.setPromptText(a.getString(com.android.internal.R.styleable.Spinner_prompt));
 
+        mDisableChildrenWhenDisabled = a.getBoolean(
+                com.android.internal.R.styleable.Spinner_disableChildrenWhenDisabled, false);
+
         a.recycle();
 
         // Base constructor can call setAdapter before we initialize mPopup.
@@ -196,6 +200,17 @@
         }
     }
 
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+        if (mDisableChildrenWhenDisabled) {
+            final int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                getChildAt(i).setEnabled(enabled);
+            }
+        }
+    }
+
     /**
      * Describes how the selected item view is positioned. Currently only the horizontal component
      * is used. The default is determined by the current theme.
@@ -398,6 +413,9 @@
         addViewInLayout(child, 0, lp);
 
         child.setSelected(hasFocus());
+        if (mDisableChildrenWhenDisabled) {
+            child.setEnabled(isEnabled());
+        }
 
         // Get measure specs
         int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d5450e4..17b8acf 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -439,17 +439,6 @@
     }
 
     /**
-     * Calls back SetupFaceLock to save the temporary gallery file if this is the backup lock.
-     * This doesn't have to verify that biometric is enabled because it's only called in that case
-    */
-    void moveTempGallery() {
-        Intent intent = new Intent().setClassName("com.android.facelock",
-                "com.android.facelock.SetupFaceLock");
-        intent.putExtra("moveTempGallery", true);
-        mContext.startActivity(intent);
-    }
-
-    /**
      * Calls back SetupFaceLock to delete the temporary gallery file
      */
     public void deleteTempGallery() {
@@ -501,8 +490,7 @@
                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
                     setLong(PASSWORD_TYPE_ALTERNATE_KEY,
                             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
-                    setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true);
-                    moveTempGallery();
+                    finishBiometricWeak();
                 }
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern
                         .size(), 0, 0, 0, 0, 0, 0);
@@ -619,8 +607,7 @@
                 } else {
                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
                     setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality));
-                    setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true);
-                    moveTempGallery();
+                    finishBiometricWeak();
                 }
                 if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                     int letters = 0;
@@ -1087,4 +1074,16 @@
         }
         return false;
     }
+
+    private void finishBiometricWeak() {
+        setBoolean(BIOMETRIC_WEAK_EVER_CHOSEN_KEY, true);
+
+        // Launch intent to show final screen, this also
+        // moves the temporary gallery to the actual gallery
+        Intent intent = new Intent();
+        intent.setClassName("com.android.facelock",
+                "com.android.facelock.SetupEndScreen");
+        mContext.startActivity(intent);
+    }
+
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 18194ee..230df39 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -423,6 +423,12 @@
         android:description="@string/permdesc_accessWifiState"
         android:label="@string/permlab_accessWifiState" />
 
+    <!-- @hide -->
+    <permission android:name="android.permission.ACCESS_WIMAX_STATE"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="normal"
+        android:description="@string/permdesc_accessWimaxState"
+        android:label="@string/permlab_accessWimaxState" />
     <!-- Allows applications to connect to paired bluetooth devices -->
     <permission android:name="android.permission.BLUETOOTH"
         android:permissionGroup="android.permission-group.NETWORK"
@@ -984,6 +990,12 @@
         android:description="@string/permdesc_changeWifiState"
         android:label="@string/permlab_changeWifiState" />
 
+    <!-- @hide -->
+    <permission android:name="android.permission.CHANGE_WIMAX_STATE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_changeWimaxState"
+        android:label="@string/permlab_changeWimaxState" />
     <!-- Allows applications to enter Wi-Fi Multicast mode -->
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -1015,6 +1027,13 @@
         android:label="@string/permlab_readLogs"
         android:description="@string/permdesc_readLogs" />
 
+    <!-- Allows an application to use any media decoder when decoding for playback
+         @hide -->
+    <permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
+        android:protectionLevel="signatureOrSystem"
+        android:label="@string/permlab_anyCodecForPlayback"
+        android:description="@string/permdesc_anyCodecForPlayback" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..c2e4b78
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..51b839f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/core/res/res/layout/action_menu_layout.xml b/core/res/res/layout/action_menu_layout.xml
index 5696d87..c401fec 100644
--- a/core/res/res/layout/action_menu_layout.xml
+++ b/core/res/res/layout/action_menu_layout.xml
@@ -18,6 +18,6 @@
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
-     android:divider="?android:attr/dividerVertical"
+     android:divider="?android:attr/actionBarDivider"
      android:dividerPadding="12dip"
      android:gravity="center_vertical" />
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 551c1d8..5b488c0 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -60,6 +60,12 @@
     <!-- Compensate for double margin : preference_screen_side_margin + 4 (frame background shadow) = -preference_screen_side_margin_negative -->
     <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
 
+    <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
+    <dimen name="default_app_widget_padding_left">12dp</dimen>
+    <dimen name="default_app_widget_padding_top">12dp</dimen>
+    <dimen name="default_app_widget_padding_right">4dp</dimen>
+    <dimen name="default_app_widget_padding_bottom">20dp</dimen>
+
     <!-- Minimum width for an action button in the menu area of an action bar -->
     <dimen name="action_button_min_width">64dip</dimen>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a40e24c..d0ab8b1 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3331,6 +3331,9 @@
         <attr name="popupPromptView" format="reference" />
         <!-- Gravity setting for positioning the currently selected item. -->
         <attr name="gravity" />
+        <!-- Whether this spinner should mark child views as enabled/disabled when
+             the spinner itself is enabled/disabled. -->
+        <attr name="disableChildrenWhenDisabled" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="DatePicker">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
old mode 100755
new mode 100644
index 48e8f1e..8b07e34
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -166,6 +166,12 @@
     </string-array>
 
     <!-- List of regexpressions describing the interface (if any) that represent tetherable
+         WiMAX interfaces.  If the device doesn't want to support tethering over Wifi this
+         should be empty.  An example would be "softap.*" -->
+    <string-array translatable="false" name="config_tether_wimax_regexs">
+    </string-array>
+
+    <!-- List of regexpressions describing the interface (if any) that represent tetherable
          bluetooth interfaces.  If the device doesn't want to support tethering over bluetooth this
          should be empty. -->
     <string-array translatable="false" name="config_tether_bluetooth_regexs">
@@ -718,4 +724,16 @@
     <!-- Default network policy warning threshold, in megabytes. -->
     <integer name="config_networkPolicyDefaultWarning">2048</integer>
 
+    <!-- Set and Unsets WiMAX -->
+    <bool name="config_wimaxEnabled">false</bool>
+    <!-- Location of the wimax framwork jar location -->
+    <string name="config_wimaxServiceJarLocation"></string>
+    <!-- Location of the wimax native library locaiton -->
+    <string name="config_wimaxNativeLibLocation"></string>
+    <!-- Name of the wimax manager class -->
+    <string name="config_wimaxManagerClassname"></string>
+    <!-- Name of the wimax service class -->
+    <string name="config_wimaxServiceClassname"></string>
+    <!-- Name of the wimax state tracker clas -->
+    <string name="config_wimaxStateTrackerClassname"></string>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 97d5afe..4d97ad2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1974,5 +1974,4 @@
   <public type="color" name="holo_orange_dark" id="0x01060019" />
   <public type="color" name="holo_purple" id="0x0106001a" />
   <public type="color" name="holo_blue_bright" id="0x0106001b" />
-
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a819173..9b8be85 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -831,6 +831,12 @@
         including personal or private information.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_anyCodecForPlayback">use any media decoder for playback</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_anyCodecForPlayback">Allows an application to use any installed
+        media decoder to decode for playback.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_diagnostic">read/write to resources owned by diag</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_diagnostic">Allows an application to read and write to
@@ -1362,6 +1368,12 @@
       than the non-multicast mode.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_accessWimaxState">view WiMAX state</string>
+    <string name="permdesc_accessWimaxState">Allows an application to view
+      the information about the state of WiMAX.</string>
+    <string name="permlab_changeWimaxState">change WiMAX state</string>
+    <string name="permdesc_changeWimaxState">Allows an application to connect
+      to and disconnect from WiMAX network.</string>
     <string name="permlab_bluetoothAdmin">bluetooth administration</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bluetoothAdmin" product="tablet">Allows an application to configure
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 949f01f..73e1a7c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1798,6 +1798,7 @@
         <item name="android:dropDownWidth">wrap_content</item>
         <item name="android:popupPromptView">@android:layout/simple_dropdown_hint</item>
         <item name="android:gravity">left|center_vertical</item>
+        <item name="android:disableChildrenWhenDisabled">true</item>
     </style>
 
     <style name="Widget.Holo.Spinner.DropDown">
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index b37eb46..098464f 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -294,6 +294,22 @@
         assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L);
     }
 
+    public void testClone() throws Exception {
+        final NetworkStats original = new NetworkStats(TEST_START, 5)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+
+        // make clone and mutate original
+        final NetworkStats clone = original.clone();
+        original.addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
+
+        assertEquals(3, original.size());
+        assertEquals(2, clone.size());
+
+        assertEquals(128L + 512L + 128L, original.getTotalBytes());
+        assertEquals(128L + 512L, clone.getTotalBytes());
+    }
+
     private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
             int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
         final NetworkStats.Entry entry = stats.getValues(index, null);
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index f3b62ec..29fab11 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -130,10 +130,17 @@
     }
 
     /**
-     * Set the size of buffers returned by requestBuffers when a width and height
-     * of zero is requested.
+     * Set the default size of the image buffers.  The image producer may override the buffer size,
+     * in which case the producer-set buffer size will be used, not the default size set by this
+     * method.  Both video and camera based image producers do override the size.  This method may
+     * be used to set the image size when producing images with {@link android.graphics.Canvas} (via
+     * {@link android.view.Surface#lockCanvas}), or OpenGL ES (via an EGLSurface).
      *
-     * @hide Pending approval by API council.
+     * The new default buffer size will take effect the next time the image producer requests a
+     * buffer to fill.  For {@link android.graphics.Canvas} this will be the next time {@link
+     * android.view.Surface#lockCanvas} is called.  For OpenGL ES, the EGLSurface should be
+     * destroyed (via eglDestroySurface), made not-current (via eglMakeCurrent), and then recreated
+     * (via eglCreateWindowSurface) to ensure that the new default size has taken effect.
      */
     public void setDefaultBufferSize(int width, int height) {
         nativeSetDefaultBufferSize(width, height);
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 0e2cdf7..e905903 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -40,7 +40,6 @@
                                     const KeyedVector<String8, String8>* headers) = 0;
     virtual status_t        setDataSource(int fd, int64_t offset, int64_t length) = 0;
     virtual status_t        setDataSource(const sp<IStreamSource>& source) = 0;
-    virtual status_t        setVideoSurface(const sp<Surface>& surface) = 0;
     virtual status_t        setVideoSurfaceTexture(
                                     const sp<ISurfaceTexture>& surfaceTexture) = 0;
     virtual status_t        prepareAsync() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 4328d3c..80f43a3 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -117,9 +117,6 @@
         return INVALID_OPERATION;
     }
 
-    // pass the buffered Surface to the media player service
-    virtual status_t    setVideoSurface(const sp<Surface>& surface) = 0;
-
     // pass the buffered ISurfaceTexture to the media player service
     virtual status_t    setVideoSurfaceTexture(
                                 const sp<ISurfaceTexture>& surfaceTexture) = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 08835fb..e6a0cc5 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -170,7 +170,6 @@
 
             status_t        setDataSource(int fd, int64_t offset, int64_t length);
             status_t        setDataSource(const sp<IStreamSource> &source);
-            status_t        setVideoSurface(const sp<Surface>& surface);
             status_t        setVideoSurfaceTexture(
                                     const sp<ISurfaceTexture>& surfaceTexture);
             status_t        setListener(const sp<MediaPlayerListener>& listener);
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 50a41ca..9c1e6b7 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -35,7 +35,6 @@
     SET_DATA_SOURCE_URL,
     SET_DATA_SOURCE_FD,
     SET_DATA_SOURCE_STREAM,
-    SET_VIDEO_SURFACE,
     PREPARE_ASYNC,
     START,
     STOP,
@@ -112,16 +111,6 @@
         return reply.readInt32();
     }
 
-    // pass the buffered Surface to the media player service
-    status_t setVideoSurface(const sp<Surface>& surface)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
-        Surface::writeToParcel(surface, &data);
-        remote()->transact(SET_VIDEO_SURFACE, data, &reply);
-        return reply.readInt32();
-    }
-
     // pass the buffered ISurfaceTexture to the media player service
     status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
     {
@@ -345,12 +334,6 @@
             reply->writeInt32(setDataSource(source));
             return NO_ERROR;
         }
-        case SET_VIDEO_SURFACE: {
-            CHECK_INTERFACE(IMediaPlayer, data, reply);
-            sp<Surface> surface = Surface::readFromParcel(data);
-            reply->writeInt32(setVideoSurface(surface));
-            return NO_ERROR;
-        } break;
         case SET_VIDEO_SURFACETEXTURE: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             sp<ISurfaceTexture> surfaceTexture =
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index f72300b..c2e1ddf 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -219,14 +219,6 @@
     return mPlayer->getMetadata(update_only, apply_filter, metadata);
 }
 
-status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
-{
-    LOGV("setVideoSurface");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return NO_INIT;
-    return mPlayer->setVideoSurface(surface);
-}
-
 status_t MediaPlayer::setVideoSurfaceTexture(
         const sp<ISurfaceTexture>& surfaceTexture)
 {
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b655358..e8d0f0c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -788,14 +788,6 @@
     return mStatus;
 }
 
-status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface)
-{
-    LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
-    sp<MediaPlayerBase> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    return p->setVideoSurface(surface);
-}
-
 void MediaPlayerService::Client::disconnectNativeWindow() {
     if (mConnectedWindow != NULL) {
         status_t err = native_window_api_disconnect(mConnectedWindow.get(),
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 62214ba..04d9e28 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -248,7 +248,6 @@
 
         // IMediaPlayer interface
         virtual void            disconnect();
-        virtual status_t        setVideoSurface(const sp<Surface>& surface);
         virtual status_t        setVideoSurfaceTexture(
                                         const sp<ISurfaceTexture>& surfaceTexture);
         virtual status_t        prepareAsync();
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index b35696f1..3469389 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -35,7 +35,6 @@
             const char* path, const KeyedVector<String8, String8> *headers);
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; }
     virtual status_t    setVideoSurfaceTexture(
                                 const sp<ISurfaceTexture>& surfaceTexture)
                             { return UNKNOWN_ERROR; }
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index cd4b1ef..598d573 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -69,12 +69,6 @@
     return mPlayer->setDataSource(source);
 }
 
-status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) {
-    LOGV("setVideoSurface");
-
-    return mPlayer->setSurface(surface);
-}
-
 status_t StagefrightPlayer::setVideoSurfaceTexture(
         const sp<ISurfaceTexture> &surfaceTexture) {
     LOGV("setVideoSurfaceTexture");
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index cbc6d49..e89e18a 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -40,7 +40,6 @@
 
     virtual status_t setDataSource(const sp<IStreamSource> &source);
 
-    virtual status_t setVideoSurface(const sp<Surface> &surface);
     virtual status_t setVideoSurfaceTexture(
             const sp<ISurfaceTexture> &surfaceTexture);
     virtual status_t prepare();
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 802a11b..91ffa7d 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -75,9 +75,6 @@
 
 
     // All the methods below wrap the mPlayer instance.
-    virtual status_t setVideoSurface(const android::sp<android::Surface>& s)  {
-        return mPlayer->setVideoSurface(s);
-    }
     virtual status_t setVideoSurfaceTexture(
             const android::sp<android::ISurfaceTexture>& st)  {
         return mPlayer->setVideoSurfaceTexture(st);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 70208f8..2a5c0a6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -99,12 +99,6 @@
     msg->post();
 }
 
-void NuPlayer::setVideoSurface(const sp<Surface> &surface) {
-    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
-    msg->setObject("native-window", new NativeWindowWrapper(surface));
-    msg->post();
-}
-
 void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
     sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
     sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index f90759d..f23deea 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -42,7 +42,6 @@
     void setDataSource(
             const char *url, const KeyedVector<String8, String8> *headers);
 
-    void setVideoSurface(const sp<Surface> &surface);
     void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
     void start();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 452ba99..5aa99bf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -89,12 +89,6 @@
     return OK;
 }
 
-status_t NuPlayerDriver::setVideoSurface(const sp<Surface> &surface) {
-    mPlayer->setVideoSurface(surface);
-
-    return OK;
-}
-
 status_t NuPlayerDriver::setVideoSurfaceTexture(
         const sp<ISurfaceTexture> &surfaceTexture) {
     mPlayer->setVideoSurfaceTexture(surfaceTexture);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index aaa3de0..4a0026c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -37,7 +37,6 @@
 
     virtual status_t setDataSource(const sp<IStreamSource> &source);
 
-    virtual status_t setVideoSurface(const sp<Surface> &surface);
     virtual status_t setVideoSurfaceTexture(
             const sp<ISurfaceTexture> &surfaceTexture);
     virtual status_t prepare();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index bf19040..640e9fa 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -381,7 +381,7 @@
         LOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
     }
 
-    entry->mNotifyConsumed->setInt32("render", true);
+    entry->mNotifyConsumed->setInt32("render", !tooLate);
     entry->mNotifyConsumed->post();
     mVideoQueue.erase(mVideoQueue.begin());
     entry = NULL;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f37e75b..7d9d7ed 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1139,18 +1139,9 @@
     return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
 }
 
-status_t AwesomePlayer::setSurface(const sp<Surface> &surface) {
-    Mutex::Autolock autoLock(mLock);
-
-    mSurface = surface;
-    return setNativeWindow_l(surface);
-}
-
 status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
     Mutex::Autolock autoLock(mLock);
 
-    mSurface.clear();
-
     status_t err;
     if (surfaceTexture != NULL) {
         err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 7d6bcad..c13d6cb 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -81,7 +81,6 @@
 
     bool isPlaying() const;
 
-    status_t setSurface(const sp<Surface> &surface);
     status_t setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
     status_t setLooping(bool shouldLoop);
@@ -154,7 +153,6 @@
     bool mUIDValid;
     uid_t mUID;
 
-    sp<Surface> mSurface;
     sp<ANativeWindow> mNativeWindow;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
 
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index ed3051b..a6fdeea 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -68,7 +68,6 @@
     }
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) {return OK;}
-    virtual status_t    setVideoSurface(const sp<Surface>& surface) {return OK;}
     virtual status_t    setVideoSurfaceTexture(
                                 const sp<ISurfaceTexture>& surfaceTexture) {return OK;}
     virtual status_t    prepare() {return OK;}
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index a08932a..8e8e26c 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -256,6 +256,21 @@
 typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
 #endif
 
+
+/* EGL_ANDROID_blob_cache
+ */
+#ifndef EGL_ANDROID_blob_cache
+#define EGL_ANDROID_blob_cache 1
+typedef khronos_ssize_t EGLsizei;
+typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, const void* value, EGLsizei valueSize);
+typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, void* value, EGLsizei valueSize);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncs(EGLDisplay dpy, EGLSetBlobFunc set, EGLGetBlobFunc get);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy,
+        EGLSetBlobFunc set, EGLGetBlobFunc get);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 1e64302..aa40d58 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -19,6 +19,21 @@
 #include "egl_impl.h"
 #include "egldefs.h"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// Cache size limits.
+static const size_t maxKeySize = 1024;
+static const size_t maxValueSize = 4096;
+static const size_t maxTotalSize = 64 * 1024;
+
+// Cache file header
+static const char* cacheFileMagic = "EGL$";
+static const size_t cacheFileHeaderSize = 8;
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -26,37 +41,37 @@
 #define BC_EXT_STR "EGL_ANDROID_blob_cache"
 
 //
-// EGL_ANDROID_blob_cache types and functions
-//
-typedef khronos_ssize_t EGLsizei;
-
-typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
-        const void* value, EGLsizei valueSize);
-
-typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
-        void* value, EGLsizei valueSize);
-
-typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy,
-        EGLSetBlobFunc set, EGLGetBlobFunc get);
-
-//
-// egl_cache_t definition
+// Callback functions passed to EGL.
 //
 static void setBlob(const void* key, EGLsizei keySize, const void* value,
         EGLsizei valueSize) {
+    egl_cache_t::get()->setBlob(key, keySize, value, valueSize);
 }
 
 static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
         EGLsizei valueSize) {
-    return 0;
+    return egl_cache_t::get()->getBlob(key, keySize, value, valueSize);
 }
 
+//
+// egl_cache_t definition
+//
+egl_cache_t::egl_cache_t() :
+        mInitialized(false),
+        mBlobCache(NULL) {
+}
+
+egl_cache_t::~egl_cache_t() {
+}
+
+egl_cache_t egl_cache_t::sCache;
+
 egl_cache_t* egl_cache_t::get() {
-    static egl_cache_t theCache;
-    return &theCache;
+    return &sCache;
 }
 
 void egl_cache_t::initialize(egl_display_t *display) {
+    Mutex::Autolock lock(mMutex);
     for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
@@ -79,7 +94,8 @@
                     continue;
                 }
 
-                eglSetBlobCacheFuncs(display->disp[i].dpy, setBlob, getBlob);
+                eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob,
+                        android::getBlob);
                 EGLint err = cnx->egl.eglGetError();
                 if (err != EGL_SUCCESS) {
                     LOGE("eglSetBlobCacheFuncs resulted in an error: %#x",
@@ -88,6 +104,210 @@
             }
         }
     }
+    mInitialized = true;
+}
+
+void egl_cache_t::terminate() {
+    Mutex::Autolock lock(mMutex);
+    if (mBlobCache != NULL) {
+        saveBlobCacheLocked();
+        mBlobCache = NULL;
+    }
+    mInitialized = false;
+}
+
+void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value,
+        EGLsizei valueSize) {
+    Mutex::Autolock lock(mMutex);
+
+    if (keySize < 0 || valueSize < 0) {
+        LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
+        return;
+    }
+
+    if (mInitialized) {
+        sp<BlobCache> bc = getBlobCacheLocked();
+        bc->set(key, keySize, value, valueSize);
+    }
+}
+
+EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value,
+        EGLsizei valueSize) {
+    Mutex::Autolock lock(mMutex);
+
+    if (keySize < 0 || valueSize < 0) {
+        LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
+        return 0;
+    }
+
+    if (mInitialized) {
+        sp<BlobCache> bc = getBlobCacheLocked();
+        return bc->get(key, keySize, value, valueSize);
+    }
+    return 0;
+}
+
+void egl_cache_t::setCacheFilename(const char* filename) {
+    Mutex::Autolock lock(mMutex);
+    mFilename = filename;
+}
+
+sp<BlobCache> egl_cache_t::getBlobCacheLocked() {
+    if (mBlobCache == NULL) {
+        mBlobCache = new BlobCache(maxKeySize, maxValueSize, maxTotalSize);
+        loadBlobCacheLocked();
+    }
+    return mBlobCache;
+}
+
+static uint32_t crc32c(const uint8_t* buf, size_t len) {
+    const uint32_t polyBits = 0x82F63B78;
+    uint32_t r = 0;
+    for (size_t i = 0; i < len; i++) {
+        r ^= buf[i];
+        for (int j = 0; j < 8; j++) {
+            if (r & 1) {
+                r = (r >> 1) ^ polyBits;
+            } else {
+                r >>= 1;
+            }
+        }
+    }
+    return r;
+}
+
+void egl_cache_t::saveBlobCacheLocked() {
+    if (mFilename.length() > 0) {
+        size_t cacheSize = mBlobCache->getFlattenedSize();
+        size_t headerSize = cacheFileHeaderSize;
+        const char* fname = mFilename.string();
+
+        // Try to create the file with no permissions so we can write it
+        // without anyone trying to read it.
+        int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+        if (fd == -1) {
+            if (errno == EEXIST) {
+                // The file exists, delete it and try again.
+                if (unlink(fname) == -1) {
+                    // No point in retrying if the unlink failed.
+                    LOGE("error unlinking cache file %s: %s (%d)", fname,
+                            strerror(errno), errno);
+                    return;
+                }
+                // Retry now that we've unlinked the file.
+                fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+            }
+            if (fd == -1) {
+                LOGE("error creating cache file %s: %s (%d)", fname,
+                        strerror(errno), errno);
+                return;
+            }
+        }
+
+        size_t fileSize = headerSize + cacheSize;
+        if (ftruncate(fd, fileSize) == -1) {
+            LOGE("error setting cache file size: %s (%d)", strerror(errno),
+                    errno);
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
+                PROT_WRITE, MAP_SHARED, fd, 0));
+        if (buf == MAP_FAILED) {
+            LOGE("error mmaping cache file: %s (%d)", strerror(errno),
+                    errno);
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        status_t err = mBlobCache->flatten(buf + headerSize, cacheSize, NULL,
+                0);
+        if (err != OK) {
+            LOGE("error writing cache contents: %s (%d)", strerror(-err),
+                    -err);
+            munmap(buf, fileSize);
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        // Write the file magic and CRC
+        memcpy(buf, cacheFileMagic, 4);
+        uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+        *crc = crc32c(buf + headerSize, cacheSize);
+
+        munmap(buf, fileSize);
+        fchmod(fd, S_IRUSR);
+        close(fd);
+    }
+}
+
+void egl_cache_t::loadBlobCacheLocked() {
+    if (mFilename.length() > 0) {
+        size_t headerSize = cacheFileHeaderSize;
+
+        int fd = open(mFilename.string(), O_RDONLY, 0);
+        if (fd == -1) {
+            if (errno != ENOENT) {
+                LOGE("error opening cache file %s: %s (%d)", mFilename.string(),
+                        strerror(errno), errno);
+            }
+            return;
+        }
+
+        struct stat statBuf;
+        if (fstat(fd, &statBuf) == -1) {
+            LOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
+            close(fd);
+            return;
+        }
+
+        // Sanity check the size before trying to mmap it.
+        size_t fileSize = statBuf.st_size;
+        if (fileSize > maxTotalSize * 2) {
+            LOGE("cache file is too large: %#llx", statBuf.st_size);
+            close(fd);
+            return;
+        }
+
+        uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
+                PROT_READ, MAP_PRIVATE, fd, 0));
+        if (buf == MAP_FAILED) {
+            LOGE("error mmaping cache file: %s (%d)", strerror(errno),
+                    errno);
+            close(fd);
+            return;
+        }
+
+        // Check the file magic and CRC
+        size_t cacheSize = fileSize - headerSize;
+        if (memcmp(buf, cacheFileMagic, 4) != 0) {
+            LOGE("cache file has bad mojo");
+            close(fd);
+            return;
+        }
+        uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+        if (crc32c(buf + headerSize, cacheSize) != *crc) {
+            LOGE("cache file failed CRC check");
+            close(fd);
+            return;
+        }
+
+        status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, 0);
+        if (err != OK) {
+            LOGE("error reading cache contents: %s (%d)", strerror(-err),
+                    -err);
+            munmap(buf, fileSize);
+            close(fd);
+            return;
+        }
+
+        munmap(buf, fileSize);
+        close(fd);
+    }
 }
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 1fcfacc..05d5873 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -14,20 +14,110 @@
  ** limitations under the License.
  */
 
+#ifndef ANDROID_EGL_CACHE_H
+#define ANDROID_EGL_CACHE_H
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <utils/BlobCache.h>
+#include <utils/String8.h>
+#include <utils/StrongPointer.h>
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
 class egl_display_t;
 
-class egl_cache_t {
+class EGLAPI egl_cache_t {
 public:
 
+    // get returns a pointer to the singleton egl_cache_t object.  This
+    // singleton object will never be destroyed.
     static egl_cache_t* get();
 
+    // initialize puts the egl_cache_t into an initialized state, such that it
+    // is able to insert and retrieve entries from the cache.  This should be
+    // called when EGL is initialized.  When not in the initialized state the
+    // getBlob and setBlob methods will return without performing any cache
+    // operations.
     void initialize(egl_display_t* display);
+
+    // terminate puts the egl_cache_t back into the uninitialized state.  When
+    // in this state the getBlob and setBlob methods will return without
+    // performing any cache operations.
+    void terminate();
+
+    // setBlob attempts to insert a new key/value blob pair into the cache.
+    // This will be called by the hardware vendor's EGL implementation via the
+    // EGL_ANDROID_blob_cache extension.
+    void setBlob(const void* key, EGLsizei keySize, const void* value,
+        EGLsizei valueSize);
+
+    // getBlob attempts to retrieve the value blob associated with a given key
+    // blob from cache.  This will be called by the hardware vendor's EGL
+    // implementation via the EGL_ANDROID_blob_cache extension.
+    EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
+        EGLsizei valueSize);
+
+    // setCacheFilename sets the name of the file that should be used to store
+    // cache contents from one program invocation to another.
+    void setCacheFilename(const char* filename);
+
+private:
+    // Creation and (the lack of) destruction is handled internally.
+    egl_cache_t();
+    ~egl_cache_t();
+
+    // Copying is disallowed.
+    egl_cache_t(const egl_cache_t&); // not implemented
+    void operator=(const egl_cache_t&); // not implemented
+
+    // getBlobCacheLocked returns the BlobCache object being used to store the
+    // key/value blob pairs.  If the BlobCache object has not yet been created,
+    // this will do so, loading the serialized cache contents from disk if
+    // possible.
+    sp<BlobCache> getBlobCacheLocked();
+
+    // saveBlobCache attempts to save the current contents of mBlobCache to
+    // disk.
+    void saveBlobCacheLocked();
+
+    // loadBlobCache attempts to load the saved cache contents from disk into
+    // mBlobCache.
+    void loadBlobCacheLocked();
+
+    // mInitialized indicates whether the egl_cache_t is in the initialized
+    // state.  It is initialized to false at construction time, and gets set to
+    // true when initialize is called.  It is set back to false when terminate
+    // is called.  When in this state, the cache behaves as normal.  When not,
+    // the getBlob and setBlob methods will return without performing any cache
+    // operations.
+    bool mInitialized;
+
+    // mBlobCache is the cache in which the key/value blob pairs are stored.  It
+    // is initially NULL, and will be initialized by getBlobCacheLocked the
+    // first time it's needed.
+    sp<BlobCache> mBlobCache;
+
+    // mFilename is the name of the file for storing cache contents in between
+    // program invocations.  It is initialized to an empty string at
+    // construction time, and can be set with the setCacheFilename method.  An
+    // empty string indicates that the cache should not be saved to or restored
+    // from disk.
+    String8 mFilename;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables. It must be locked whenever the member variables are accessed.
+    mutable Mutex mMutex;
+
+    // sCache is the singleton egl_cache_t object.
+    static egl_cache_t sCache;
 };
 
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
+
+#endif // ANDROID_EGL_CACHE_H
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 0f92864..558ca77 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -44,6 +44,7 @@
 
 egl_display_t::~egl_display_t() {
     magic = 0;
+    egl_cache_t::get()->terminate();
 }
 
 egl_display_t* egl_display_t::get(EGLDisplay dpy) {
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 113595f..1c1092c 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -59,7 +59,7 @@
 
 // ----------------------------------------------------------------------------
 
-class egl_display_t {
+class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
     static egl_display_t sDisplay[NUM_DISPLAYS];
     EGLDisplay getDisplay(EGLNativeDisplayType display);
 
@@ -141,4 +141,3 @@
 // ----------------------------------------------------------------------------
 
 #endif // ANDROID_EGL_DISPLAY_H
-
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
index 92d7eb1..14104d17 100644
--- a/opengl/tests/EGLTest/Android.mk
+++ b/opengl/tests/EGLTest/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
+    egl_cache_test.cpp \
     EGL_test.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
@@ -21,9 +22,12 @@
 
 LOCAL_C_INCLUDES := \
     bionic \
+    bionic/libc/private \
     bionic/libstdc++/include \
     external/gtest/include \
     external/stlport/stlport \
+    frameworks/base/opengl/libs \
+    frameworks/base/opengl/libs/EGL \
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/opengl/tests/EGLTest/egl_cache_test.cpp b/opengl/tests/EGLTest/egl_cache_test.cpp
new file mode 100644
index 0000000..c7d9e3e
--- /dev/null
+++ b/opengl/tests/EGLTest/egl_cache_test.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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 "EGL_test"
+//#define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+
+#include <utils/Log.h>
+
+#include "egl_cache.h"
+#include "egl_display.h"
+
+namespace android {
+
+class EGLCacheTest : public ::testing::Test {
+protected:
+    virtual void SetUp() {
+        mCache = egl_cache_t::get();
+    }
+
+    virtual void TearDown() {
+        mCache->setCacheFilename("");
+        mCache->terminate();
+    }
+
+    egl_cache_t* mCache;
+};
+
+TEST_F(EGLCacheTest, UninitializedCacheAlwaysMisses) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mCache->setBlob("abcd", 4, "efgh", 4);
+    ASSERT_EQ(0, mCache->getBlob("abcd", 4, buf, 4));
+    ASSERT_EQ(0xee, buf[0]);
+    ASSERT_EQ(0xee, buf[1]);
+    ASSERT_EQ(0xee, buf[2]);
+    ASSERT_EQ(0xee, buf[3]);
+}
+
+TEST_F(EGLCacheTest, InitializedCacheAlwaysHits) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
+    mCache->setBlob("abcd", 4, "efgh", 4);
+    ASSERT_EQ(4, mCache->getBlob("abcd", 4, buf, 4));
+    ASSERT_EQ('e', buf[0]);
+    ASSERT_EQ('f', buf[1]);
+    ASSERT_EQ('g', buf[2]);
+    ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(EGLCacheTest, TerminatedCacheAlwaysMisses) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
+    mCache->setBlob("abcd", 4, "efgh", 4);
+    mCache->terminate();
+    ASSERT_EQ(0, mCache->getBlob("abcd", 4, buf, 4));
+    ASSERT_EQ(0xee, buf[0]);
+    ASSERT_EQ(0xee, buf[1]);
+    ASSERT_EQ(0xee, buf[2]);
+    ASSERT_EQ(0xee, buf[3]);
+}
+
+class EGLCacheSerializationTest : public EGLCacheTest {
+
+protected:
+
+    virtual void SetUp() {
+        EGLCacheTest::SetUp();
+
+        char* tn = tempnam("/sdcard", "EGL_test-cache-");
+        mFilename = tn;
+        free(tn);
+    }
+
+    virtual void TearDown() {
+        unlink(mFilename.string());
+        EGLCacheTest::TearDown();
+    }
+
+    String8 mFilename;
+};
+
+TEST_F(EGLCacheSerializationTest, ReinitializedCacheContainsValues) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mCache->setCacheFilename(mFilename);
+    mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
+    mCache->setBlob("abcd", 4, "efgh", 4);
+    mCache->terminate();
+    mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
+    ASSERT_EQ(4, mCache->getBlob("abcd", 4, buf, 4));
+    ASSERT_EQ('e', buf[0]);
+    ASSERT_EQ('f', buf[1]);
+    ASSERT_EQ('g', buf[2]);
+    ASSERT_EQ('h', buf[3]);
+}
+
+}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 3920257..0891525 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -21,7 +21,7 @@
     <integer name="def_screen_off_timeout">60000</integer>
     <bool name="def_airplane_mode_on">false</bool>
     <!-- Comma-separated list of bluetooth, wifi, and cell. -->
-    <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc</string>
+    <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc,wimax</string>
     <string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi,nfc</string>
     <bool name="def_auto_time">true</bool>
     <bool name="def_auto_time_zone">true</bool>
@@ -133,4 +133,8 @@
     <bool name="def_dtmf_tones_enabled">true</bool>
     <!-- Default for UI touch sounds enabled -->
     <bool name="def_sound_effects_enabled">true</bool>
+
+    <!-- Default for Messaging app notifications enabled -->
+    <bool name="def_messaging_app_notifications_on">true</bool>
+
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5495d08..44194f0 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1472,6 +1472,10 @@
 
             loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
                     R.bool.def_touch_exploration_enabled);
+
+            loadBooleanSetting(stmt, Settings.Secure.MESSAGING_APP_NOTIFICATIONS,
+                    R.bool.def_messaging_app_notifications_on);
+
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png
new file mode 100644
index 0000000..f24d801
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png
new file mode 100644
index 0000000..66eb5db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png
new file mode 100644
index 0000000..edff74a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png
new file mode 100644
index 0000000..1cdd4eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png
new file mode 100644
index 0000000..95fdaf9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png
new file mode 100644
index 0000000..8678e39
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png
new file mode 100644
index 0000000..1d2d290
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..c2e4b78
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..51b839f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png
new file mode 100644
index 0000000..b20c5c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index eb644b3..93ac22e 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -52,6 +52,27 @@
         android:id="@+id/spacer"
         />
     <FrameLayout
+        android:id="@+id/wimax_combo"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginRight="-6dp"
+        >
+        <ImageView
+            android:id="@+id/wimax_signal"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:scaleType="center"
+            />
+        <ImageView
+            android:id="@+id/wimax_inout"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center|bottom"
+            />
+    </FrameLayout>
+    <FrameLayout
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         >
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 93ec481..089a54d 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -18,8 +18,9 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- For formatting day of week and date in DateView.  %1$s is DOW, %2$s is date.
-         In Roman locales we now show only the date, but DOW is available for other locales if
-         necessary. -->
-    <string name="status_bar_date_formatter">%2$s</string>
+         We show both (DOW on one line, then the date) but this can be overridden for locales as
+         necessary.
+         -->
+    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
 
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1a6cae2..a0d7b13 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -256,7 +256,12 @@
     <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_wifi_three_bars">Wi-Fi three bars.</string>
     <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_wifi_signal_full">Wi-Fi signal full.</string>
+    <string name="accessibility_wifi_signal_full">WiFi signal full.</string>
+    <string name="accessibility_no_wimax">No WiMAX.</string>
+    <string name="accessibility_wimax_one_bar">WiMAX one bar.</string>
+    <string name="accessibility_wimax_two_bars">WiMAX two bars.</string>
+    <string name="accessibility_wimax_three_bars">WiMAX three bars.</string>
+    <string name="accessibility_wimax_signal_full">WiMAX signal full.</string>
 
     <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_gprs">GPRS</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c6a59d3..b0e6968 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -350,7 +350,11 @@
                 (SignalClusterView)sb.findViewById(R.id.signal_cluster);
         mNetworkController.addSignalCluster(signalCluster);
         signalCluster.setNetworkController(mNetworkController);
-
+	final ImageView wimaxRSSI = 
+                (ImageView)sb.findViewById(R.id.wimax_signal);
+        if (wimaxRSSI != null) {
+            mNetworkController.addWimaxIconView(wimaxRSSI);
+        }
         // Recents Panel
         mRecentTasksLoader = new RecentTasksLoader(context);
         updateRecentsPanel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
index 13fb03e..f45426b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -34,4 +34,11 @@
         R.string.accessibility_wifi_three_bars,
         R.string.accessibility_wifi_signal_full
     };
+    static final int[] WIMAX_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_wimax,
+        R.string.accessibility_wimax_one_bar,
+        R.string.accessibility_wimax_two_bars,
+        R.string.accessibility_wimax_three_bars,
+        R.string.accessibility_wimax_signal_full
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index a305816..f77e93f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -31,6 +31,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.net.wimax.WimaxManagerConstants;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
@@ -90,6 +91,7 @@
 
     String mContentDescriptionPhoneSignal;
     String mContentDescriptionWifi;
+    String mContentDescriptionWimax;
     String mContentDescriptionCombinedSignal;
     String mContentDescriptionDataType;
 
@@ -108,6 +110,14 @@
     private int mBluetoothTetherIconId =
         com.android.internal.R.drawable.stat_sys_tether_bluetooth;
 
+    //wimax
+    private boolean mIsWimaxEnabled = false;
+    private boolean mWimaxConnected = false;
+    private boolean mWimaxIdle = false;
+    private int mWimaxIconId = 0;
+    private int mWimaxSignal = 0;
+    private int mWimaxState = 0;
+    private int mWimaxExtraState = 0;
     // data connectivity (regardless of state, can we access the internet?)
     // state of inet connection - 0 not connected, 100 connected
     private int mInetCondition = 0;
@@ -121,6 +131,7 @@
     ArrayList<ImageView> mDataDirectionIconViews = new ArrayList<ImageView>();
     ArrayList<ImageView> mDataDirectionOverlayIconViews = new ArrayList<ImageView>();
     ArrayList<ImageView> mWifiIconViews = new ArrayList<ImageView>();
+    ArrayList<ImageView> mWimaxIconViews = new ArrayList<ImageView>();
     ArrayList<ImageView> mCombinedSignalIconViews = new ArrayList<ImageView>();
     ArrayList<ImageView> mDataTypeIconViews = new ArrayList<ImageView>();
     ArrayList<TextView> mLabelViews = new ArrayList<TextView>();
@@ -129,6 +140,7 @@
     int mLastDataDirectionIconId = -1;
     int mLastDataDirectionOverlayIconId = -1;
     int mLastWifiIconId = -1;
+    int mLastWimaxIconId = -1;
     int mLastCombinedSignalIconId = -1;
     int mLastDataTypeIconId = -1;
     String mLastLabel = "";
@@ -164,6 +176,7 @@
 
         // set up the default wifi icon, used when no radios have ever appeared
         updateWifiIcons();
+        updateWimaxIcons();
 
         // telephony
         mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -200,6 +213,13 @@
         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        boolean isWimaxConfigEnabled = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wimaxEnabled);
+        if(isWimaxConfigEnabled) {
+            filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION);
+            filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION);
+            filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION);
+        }
         context.registerReceiver(this, filter);
 
         // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
@@ -224,6 +244,9 @@
     public void addWifiIconView(ImageView v) {
         mWifiIconViews.add(v);
     }
+    public void addWimaxIconView(ImageView v) {
+        mWimaxIconViews.add(v);
+    }
 
     public void addCombinedSignalIconView(ImageView v) {
         mCombinedSignalIconViews.add(v);
@@ -285,6 +308,11 @@
         } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
             updateAirplaneMode();
             refreshViews();
+        } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) ||
+                action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) ||
+                action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
+           updateWimaxState(intent);
+            refreshViews();
         }
     }
 
@@ -735,6 +763,51 @@
     }
 
 
+ // ===== Wimax ===================================================================
+
+    private final void updateWimaxState(Intent intent) {
+        final String action = intent.getAction();
+        boolean wasConnected = mWimaxConnected;
+        if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) {
+            int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE,
+                    WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
+            mIsWimaxEnabled = (wimaxStatus ==
+		WimaxManagerConstants.NET_4G_STATE_ENABLED)? true : false;
+        } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) {
+            mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0);
+        } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
+		mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE,
+                    WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
+            mWimaxExtraState = intent.getIntExtra(
+                    WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL,
+                    WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
+            mWimaxConnected = (mWimaxState ==
+		WimaxManagerConstants.WIMAX_STATE_CONNECTED) ? true : false;
+            mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE)? true : false;
+        }
+        updateWimaxIcons();
+    }
+       private void updateWimaxIcons() {
+            Slog.d(TAG, "in ....  updateWimaxIcons function    :  "+mIsWimaxEnabled);
+                if (mIsWimaxEnabled) {
+                        if (mWimaxConnected) {
+                                Slog.d(TAG, "in ....  updateWimaxIcons function WiMAX COnnected");
+                                if (mWimaxIdle)
+                                        mWimaxIconId = WimaxIcons.WIMAX_IDLE;
+                                else
+                                        mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal];
+                                mContentDescriptionWimax = mContext.getString(
+                                                AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]);
+                        } else {
+                                 Slog.d(TAG, "in ....  updateWimaxIcons function WiMAX Disconnected");
+                                mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED;
+                                mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax);
+                        }
+                } else {
+                         Slog.d(TAG, "in ....  updateWimaxIcons function wimax icon id 0");
+                        mWimaxIconId = 0;
+                }
+        }
     // ===== Full or limited Internet connectivity ==================================
 
     private void updateConnectivity(Intent intent) {
@@ -761,6 +834,7 @@
 
         // We want to update all the icons, all at once, for any condition change
         updateDataNetType();
+		updateWimaxIcons();
         updateDataIcon();
         updateTelephonySignalStrength();
         updateWifiIcons();
@@ -945,6 +1019,21 @@
             }
         }
 
+        // the wimax icon on phones
+        if (mLastWimaxIconId != mWimaxIconId) {
+            mLastWimaxIconId = mWimaxIconId;
+            N = mWimaxIconViews.size();
+            for (int i=0; i<N; i++) {
+                final ImageView v = mWimaxIconViews.get(i);
+                if (mWimaxIconId == 0) {
+                    v.setVisibility(View.INVISIBLE);
+                } else {
+                    v.setVisibility(View.VISIBLE);
+                    v.setImageResource(mWimaxIconId);
+                    v.setContentDescription(mContentDescriptionWimax);
+                }
+           }
+        }
         // the combined data signal icon
         if (mLastCombinedSignalIconId != combinedSignalIconId) {
             mLastCombinedSignalIconId = combinedSignalIconId;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
new file mode 100644
index 0000000..8605489
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
@@ -0,0 +1,37 @@
+/*

+ * Copyright (C) 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.

+ * 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.systemui.statusbar.policy;

+

+import com.android.systemui.R;

+

+class WimaxIcons {

+    static final int[][] WIMAX_SIGNAL_STRENGTH = {

+	{ R.drawable.stat_sys_data_wimax_signal_0,

+            R.drawable.stat_sys_data_wimax_signal_1,

+            R.drawable.stat_sys_data_wimax_signal_2,

+            R.drawable.stat_sys_data_wimax_signal_3 },

+          { R.drawable.stat_sys_data_wimax_signal_0_fully,

+            R.drawable.stat_sys_data_wimax_signal_1_fully,

+            R.drawable.stat_sys_data_wimax_signal_2_fully,

+            R.drawable.stat_sys_data_wimax_signal_3_fully }

+        };

+

+    static final int WIMAX_DISCONNECTED =

+            R.drawable.stat_sys_data_wimax_signal_disconnected;

+    static final int WIMAX_IDLE = R.drawable.stat_sys_data_wimax_signal_idle;

+    static final int WIFI_LEVEL_COUNT = WIMAX_SIGNAL_STRENGTH[0].length;

+}

diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 81e1901..0f21bdb 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -360,8 +360,7 @@
                 mHasOverlay = true;
 
                 // Continue showing FaceLock area until dialer comes up or call is resumed
-                if (mLockPatternUtils.usingBiometricWeak() &&
-                        mLockPatternUtils.isBiometricWeakInstalled() && mFaceLockServiceRunning) {
+                if (usingFaceLock() && mFaceLockServiceRunning) {
                     showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
                 }
 
@@ -582,8 +581,7 @@
             bindToFaceLock();
             // Show FaceLock area, but only for a little bit so lockpattern will become visible if
             // FaceLock fails to start or crashes
-            if (mLockPatternUtils.usingBiometricWeak() &&
-                    mLockPatternUtils.isBiometricWeakInstalled()) {
+            if (usingFaceLock()) {
                 showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT);
             }
         } else {
@@ -653,11 +651,10 @@
             ((KeyguardScreen) mUnlockScreen).onResume();
         }
 
-        if (mLockPatternUtils.usingBiometricWeak() &&
-            mLockPatternUtils.isBiometricWeakInstalled() && !mHasOverlay) {
+        if (usingFaceLock() && !mHasOverlay) {
             // Note that show() gets called before the screen turns off to set it up for next time
             // it is turned on.  We don't want to set a timeout on the FaceLock area here because it
-            // may be gone by the time the screen is turned on again.  We set the timout when the
+            // may be gone by the time the screen is turned on again.  We set the timeout when the
             // screen turns on instead.
             showFaceLockArea();
         } else {
@@ -854,7 +851,9 @@
         if (mode == Mode.UnlockScreen) {
             final UnlockMode unlockMode = getUnlockMode();
             if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
+                boolean restartFaceLock = stopFaceLockIfRunning();
                 recreateUnlockScreen(unlockMode);
+                if (restartFaceLock) activateFaceLockIfAble();
             }
         }
 
@@ -1147,28 +1146,33 @@
 
     // Everything below pertains to FaceLock - might want to separate this out
 
-    // Take care of FaceLock area when layout is created
+    // Indicates whether FaceLock is in use
+    private boolean usingFaceLock() {
+        return (mLockPatternUtils.usingBiometricWeak() &&
+                mLockPatternUtils.isBiometricWeakInstalled());
+    }
+
+    // Takes care of FaceLock area when layout is created
     private void initializeFaceLockAreaView(View view) {
-        if (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled()) {
+        if (usingFaceLock()) {
             mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView);
             if (mFaceLockAreaView == null) {
                 Log.e(TAG, "Layout does not have faceLockAreaView and FaceLock is enabled");
-            } else {
-                if (mBoundToFaceLockService) {
-                    // If we are creating a layout when we are already bound to FaceLock, then we
-                    // are undergoing an orientation change.  Stop FaceLock and restart it in the
-                    // new location.
-                    if (DEBUG) Log.d(TAG, "Restarting FL - creating view while already bound");
-                    stopAndUnbindFromFaceLock();
-                    activateFaceLockIfAble();
-                }
             }
         } else {
             mFaceLockAreaView = null; // Set to null if not using FaceLock
         }
     }
 
+    // Stops FaceLock if it is running and reports back whether it was running or not
+    private boolean stopFaceLockIfRunning() {
+        if (usingFaceLock() && mBoundToFaceLockService) {
+            stopAndUnbindFromFaceLock();
+            return true;
+        }
+        return false;
+    }
+
     // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
     // This needs to be done in a handler because the call could be coming from a callback from the
     // FaceLock service that is in a thread that can't modify the UI
@@ -1221,8 +1225,7 @@
     // Binds to FaceLock service.  This call does not tell it to start, but it causes the service
     // to call the onServiceConnected callback, which then starts FaceLock.
     public void bindToFaceLock() {
-        if (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled()) {
+        if (usingFaceLock()) {
             if (!mBoundToFaceLockService) {
                 if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
                 mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
@@ -1238,8 +1241,7 @@
 
     // Tells FaceLock to stop and then unbinds from the FaceLock service
     public void stopAndUnbindFromFaceLock() {
-        if (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled()) {
+        if (usingFaceLock()) {
             stopFaceLock();
 
             if (mBoundToFaceLockService) {
@@ -1300,8 +1302,7 @@
     // Tells the FaceLock service to start displaying its UI and perform recognition
     public void startFaceLock(IBinder windowToken, int x, int y, int h, int w)
     {
-        if (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled()) {
+        if (usingFaceLock()) {
             synchronized (mFaceLockServiceRunningLock) {
                 if (!mFaceLockServiceRunning) {
                     if (DEBUG) Log.d(TAG, "Starting FaceLock");
@@ -1322,8 +1323,7 @@
     // Tells the FaceLock service to stop displaying its UI and stop recognition
     public void stopFaceLock()
     {
-        if (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled()) {
+        if (usingFaceLock()) {
             // Note that attempting to stop FaceLock when it's not running is not an issue.
             // FaceLock can return, which stops it and then we try to stop it when the
             // screen is turned off.  That's why we check.
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 3469483..24a2420 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -34,6 +34,7 @@
 import android.widget.*;
 import android.util.Log;
 import android.media.AudioManager;
+import android.provider.MediaStore;
 import android.provider.Settings;
 
 import java.io.File;
@@ -225,9 +226,10 @@
                 mCallback.goToUnlockScreen();
             } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape
                 if (!mCameraDisabled) {
-                    // Broadcast an intent to start the Camera
-                    Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
-                    mContext.sendOrderedBroadcast(intent, null);
+                    // Start the Camera
+                    Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    mContext.startActivity(intent);
                     mCallback.goToUnlockScreen();
                 } else {
                     toggleRingMode();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7d97246..aa1c81c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -493,7 +493,9 @@
             return true;
         }
         if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
-                (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) {
+                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
+                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
             // enable accelerometer if we are docked in a dock that enables accelerometer
             // orientation management,
             return true;
@@ -3137,7 +3139,9 @@
                 // enable 180 degree rotation while docked.
                 preferredRotation = mCarDockEnablesAccelerometer
                         ? sensorRotation : mCarDockRotation;
-            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
+            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
+                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
                     && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
                 // Ignore sensor when in desk dock unless explicitly enabled.
                 // This case can override the behavior of NOSENSOR, and can also
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 96e8eb9..ff262f1 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2066,9 +2066,14 @@
         // The first time a track is added we wait
         // for all its buffers to be filled before processing it
         mAudioMixer->setActiveTrack(track->name());
-        // make sure that we have enough frames to mix one full buffer
+        // make sure that we have enough frames to mix one full buffer.
+        // enforce this condition only once to enable draining the buffer in case the client
+        // app does not call stop() and relies on underrun to stop:
+        // hence the test on (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed
+        // during last round
         uint32_t minFrames = 1;
-        if (!track->isStopped() && !track->isPausing()) {
+        if (!track->isStopped() && !track->isPausing() &&
+                (track->mRetryCount >= kMaxTrackRetries)) {
             if (t->sampleRate() == (int)mSampleRate) {
                 minFrames = mFrameCount;
             } else {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 8c42f31..4af6112 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -26,8 +26,10 @@
 import android.bluetooth.BluetoothTetheringDataTracker;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.DummyDataStateTracker;
@@ -51,6 +53,7 @@
 import android.net.ProxyProperties;
 import android.net.RouteInfo;
 import android.net.wifi.WifiStateTracker;
+import android.net.wimax.WimaxManagerConstants;
 import android.os.Binder;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -78,10 +81,14 @@
 import com.android.server.connectivity.Vpn;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Sets;
-
+import dalvik.system.DexClassLoader;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.InvocationTargetException;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -491,6 +498,12 @@
                 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
                 mNetTrackers[netType].startMonitoring(context, mHandler);
                 break;
+            case ConnectivityManager.TYPE_WIMAX:
+                mNetTrackers[netType] = makeWimaxStateTracker();
+                if (mNetTrackers[netType]!= null) {
+                    mNetTrackers[netType].startMonitoring(context, mHandler);
+                }
+                break;
             case ConnectivityManager.TYPE_ETHERNET:
                 mNetTrackers[netType] = EthernetDataTracker.getInstance();
                 mNetTrackers[netType].startMonitoring(context, mHandler);
@@ -531,7 +544,81 @@
 
         loadGlobalProxy();
     }
+private NetworkStateTracker makeWimaxStateTracker() {
+        //Initialize Wimax
+        DexClassLoader wimaxClassLoader;
+        Class wimaxStateTrackerClass = null;
+        Class wimaxServiceClass = null;
+        Class wimaxManagerClass;
+        String wimaxJarLocation;
+        String wimaxLibLocation;
+        String wimaxManagerClassName;
+        String wimaxServiceClassName;
+        String wimaxStateTrackerClassName;
 
+        NetworkStateTracker wimaxStateTracker = null;
+
+        boolean isWimaxEnabled = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wimaxEnabled);
+
+        if (isWimaxEnabled) {
+            try {
+                wimaxJarLocation = mContext.getResources().getString(
+                        com.android.internal.R.string.config_wimaxServiceJarLocation);
+                wimaxLibLocation = mContext.getResources().getString(
+                        com.android.internal.R.string.config_wimaxNativeLibLocation);
+                wimaxManagerClassName = mContext.getResources().getString(
+                        com.android.internal.R.string.config_wimaxManagerClassname);
+                wimaxServiceClassName = mContext.getResources().getString(
+                        com.android.internal.R.string.config_wimaxServiceClassname);
+                wimaxStateTrackerClassName = mContext.getResources().getString(
+                        com.android.internal.R.string.config_wimaxStateTrackerClassname);
+
+                log("wimaxJarLocation: " + wimaxJarLocation);
+                wimaxClassLoader =  new DexClassLoader(wimaxJarLocation,
+                        new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
+                        wimaxLibLocation, ClassLoader.getSystemClassLoader());
+
+                try {
+                    wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
+                    wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
+                    wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
+                } catch (ClassNotFoundException ex) {
+                    loge("Exception finding Wimax classes: " + ex.toString());
+                    return null;
+                }
+            } catch(Resources.NotFoundException ex) {
+                loge("Wimax Resources does not exist!!! ");
+                return null;
+            }
+
+            try {
+                log("Starting Wimax Service... ");
+
+                Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
+                        (new Class[] {Context.class, Handler.class});
+                wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,
+                        mHandler);
+
+                Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
+                        (new Class[] {Context.class, wimaxStateTrackerClass});
+                wmxSrvConst.setAccessible(true);
+                IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(mContext, wimaxStateTracker);
+                wmxSrvConst.setAccessible(false);
+
+                ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
+
+            } catch(Exception ex) {
+                loge("Exception creating Wimax classes: " + ex.toString());
+                return null;
+            }
+        } else {
+            loge("Wimax is not enabled or not added to the network attributes!!! ");
+            return null;
+        }
+
+        return wimaxStateTracker;
+    }
     /**
      * Sets the preferred network.
      * @param preference the new preference
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index dea9007..64789d3 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -82,7 +82,9 @@
                         // Don't force screen on when undocking from the desk dock.
                         // The change in power state will do this anyway.
                         // FIXME - we should be configurable.
-                        if (mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK ||
+                        if ((mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK
+                                && mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK
+                                && mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) ||
                                 mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
                             mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(),
                                     false, true);
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 6887de3..da960ae 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1136,12 +1136,14 @@
             final StringBuilder command = new StringBuilder();
             command.append("bandwidth removeiquota ").append(iface);
 
+            mActiveQuotaIfaces.remove(iface);
+            mActiveAlertIfaces.remove(iface);
+
             try {
                 // TODO: support quota shared across interfaces
                 mConnector.doCommand(command.toString());
-                mActiveQuotaIfaces.remove(iface);
-                mActiveAlertIfaces.remove(iface);
             } catch (NativeDaemonConnectorException e) {
+                // TODO: include current iptables state
                 throw new IllegalStateException("Error communicating to native daemon", e);
             }
         }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 1b0addf..6b23b33 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -100,10 +100,13 @@
     private static final int LONG_KEYLIGHT_DELAY = 6000;        // t+6 sec
     private static final int LONG_DIM_TIME = 7000;              // t+N-5 sec
 
-    // How long to wait to debounce light sensor changes.
+    // How long to wait to debounce light sensor changes in milliseconds
     private static final int LIGHT_SENSOR_DELAY = 2000;
 
-    // For debouncing the proximity sensor.
+    // light sensor events rate in microseconds
+    private static final int LIGHT_SENSOR_RATE = 1000000;
+
+    // For debouncing the proximity sensor in milliseconds
     private static final int PROXIMITY_SENSOR_DELAY = 1000;
 
     // trigger proximity if distance is less than 5 cm
@@ -3049,7 +3052,7 @@
             try {
                 if (enable) {
                     mSensorManager.registerListener(mLightListener, mLightSensor,
-                            SensorManager.SENSOR_DELAY_NORMAL);
+                            LIGHT_SENSOR_RATE);
                 } else {
                     mSensorManager.unregisterListener(mLightListener);
                     mHandler.removeCallbacks(mAutoBrightnessTask);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 01eade1..3c65255 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -619,12 +619,7 @@
      */
     public WifiConfiguration getWifiApConfiguration() {
         enforceAccessPermission();
-        if (mWifiStateMachineChannel != null) {
-            return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel);
-        } else {
-            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
-            return null;
-        }
+        return mWifiStateMachine.syncGetWifiApConfiguration();
     }
 
     /**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 4fe8119..05d42ada 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1220,6 +1220,8 @@
                 }
                 Thread thread = new Thread() {
                     @Override public void run() {
+                        StringBuilder dropBuilder = new StringBuilder(1024);
+                        StringBuilder logBuilder = new StringBuilder(1024);
                         try {
                             java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
                                     "procrank", });
@@ -1233,16 +1235,29 @@
                                     break;
                                 }
                                 if (line.length() > 0) {
-                                    Slog.i(TAG, line);
+                                    logBuilder.append(line);
+                                    logBuilder.append('\n');
                                 }
+                                dropBuilder.append(line);
+                                dropBuilder.append('\n');
                             }
                             converter.close();
                         } catch (IOException e) {
                         }
                         StringWriter sw = new StringWriter();
                         PrintWriter pw = new PrintWriter(sw);
-                        dumpApplicationMemoryUsage(null, pw, "  ", new String[] { }, true);
-                        Slog.i(TAG, sw.toString());
+                        StringWriter catSw = new StringWriter();
+                        PrintWriter catPw = new PrintWriter(catSw);
+                        dumpApplicationMemoryUsage(null, pw, "  ", new String[] { }, true, catPw);
+                        String memUsage = sw.toString();
+                        dropBuilder.append('\n');
+                        dropBuilder.append(memUsage);
+                        dropBuilder.append(catSw.toString());
+                        logBuilder.append(memUsage);
+                        addErrorToDropBox("watchdog", null, "system_server", null,
+                                null, "Low on memory -- no more background processes",
+                                dropBuilder.toString(), null, null);
+                        Slog.i(TAG, logBuilder.toString());
                         synchronized (ActivityManagerService.this) {
                             long now = SystemClock.uptimeMillis();
                             if (mLastMemUsageReportTime < now) {
@@ -1394,7 +1409,7 @@
                 return;
             }
 
-            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false);
+            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
         }
     }
 
@@ -3192,7 +3207,49 @@
                     return;
                 }
                 killPackageProcessesLocked(packageName, pkgUid,
-                        ProcessList.SERVICE_ADJ, false, true, true, false);
+                        ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
+    public void killAllBackgroundProcesses() {
+        if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            synchronized(this) {
+                ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
+                for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+                    final int NA = apps.size();
+                    for (int ia=0; ia<NA; ia++) {
+                        ProcessRecord app = apps.valueAt(ia);
+                        if (app.persistent) {
+                            // we don't kill persistent processes
+                            continue;
+                        }
+                        if (app.removed) {
+                            procs.add(app);
+                        } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+                            app.removed = true;
+                            procs.add(app);
+                        }
+                    }
+                }
+                
+                int N = procs.size();
+                for (int i=0; i<N; i++) {
+                    removeProcessLocked(procs.get(i), false, true, "kill all background");
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -3364,7 +3421,7 @@
     
     private final boolean killPackageProcessesLocked(String packageName, int uid,
             int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
-            boolean evenPersistent) {
+            boolean evenPersistent, String reason) {
         ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
 
         // Remove all processes this package may have touched: all with the
@@ -3399,7 +3456,7 @@
         
         int N = procs.size();
         for (int i=0; i<N; i++) {
-            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
+            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
         }
         return N > 0;
     }
@@ -3430,7 +3487,7 @@
         }
         
         boolean didSomething = killPackageProcessesLocked(name, uid, -100,
-                callerWillRestart, false, doit, evenPersistent);
+                callerWillRestart, false, doit, evenPersistent, "force stop");
         
         TaskRecord lastTask = null;
         for (i=0; i<mMainStack.mHistory.size(); i++) {
@@ -3518,11 +3575,11 @@
     }
 
     private final boolean removeProcessLocked(ProcessRecord app,
-            boolean callerWillRestart, boolean allowRestart) {
+            boolean callerWillRestart, boolean allowRestart, String reason) {
         final String name = app.processName;
         final int uid = app.info.uid;
         if (DEBUG_PROCESSES) Slog.d(
-            TAG, "Force removing process " + app + " (" + name
+            TAG, "Force removing proc " + app.toShortString() + " (" + name
             + "/" + uid + ")");
 
         mProcessNames.remove(name, uid);
@@ -3537,9 +3594,10 @@
                 mPidsSelfLocked.remove(pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }
+            Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
             handleAppDiedLocked(app, true, allowRestart);
             mLruProcesses.remove(app);
-            Process.killProcess(pid);
+            Process.killProcessQuiet(pid);
             
             if (app.persistent) {
                 if (!callerWillRestart) {
@@ -6846,7 +6904,7 @@
                 for (int i=procsToKill.size()-1; i>=0; i--) {
                     ProcessRecord proc = procsToKill.get(i);
                     Slog.i(TAG, "Removing system update proc: " + proc);
-                    removeProcessLocked(proc, true, false);
+                    removeProcessLocked(proc, true, false, "system update done");
                 }
             }
             
@@ -7042,7 +7100,7 @@
                 // Don't let services in this process be restarted and potentially
                 // annoy the user repeatedly.  Unless it is persistent, since those
                 // processes run critical code.
-                removeProcessLocked(app, false, false);
+                removeProcessLocked(app, false, false, "crash");
                 mMainStack.resumeTopActivityLocked(null);
                 return false;
             }
@@ -9298,8 +9356,10 @@
     }
 
     final void dumpApplicationMemoryUsage(FileDescriptor fd,
-            PrintWriter pw, String prefix, String[] args, boolean brief) {
+            PrintWriter pw, String prefix, String[] args, boolean brief,
+            PrintWriter categoryPw) {
         boolean dumpAll = false;
+        boolean oomOnly = false;
         
         int opti = 0;
         while (opti < args.length) {
@@ -9310,9 +9370,12 @@
             opti++;
             if ("-a".equals(opt)) {
                 dumpAll = true;
+            } else if ("--oom".equals(opt)) {
+                oomOnly = true;
             } else if ("-h".equals(opt)) {
-                pw.println("meminfo dump options: [-a] [process]");
+                pw.println("meminfo dump options: [-a] [--oom] [process]");
                 pw.println("  -a: include all available information for each process.");
+                pw.println("  --oom: only show processes organized by oom adj.");
                 pw.println("If [process] is specified it can be the name or ");
                 pw.println("pid of a specific process to dump.");
                 return;
@@ -9438,7 +9501,7 @@
                 }
             }
 
-            if (!brief) {
+            if (!brief && !oomOnly) {
                 pw.println();
                 pw.println("Total PSS by process:");
                 dumpMemItems(pw, "  ", procMems, true);
@@ -9446,10 +9509,11 @@
             }
             pw.println("Total PSS by OOM adjustment:");
             dumpMemItems(pw, "  ", oomMems, false);
-            if (!brief) {
-                pw.println();
-                pw.println("Total PSS by category:");
-                dumpMemItems(pw, "  ", catMems, true);
+            if (!oomOnly) {
+                PrintWriter out = categoryPw != null ? categoryPw : pw;
+                out.println();
+                out.println("Total PSS by category:");
+                dumpMemItems(out, "  ", catMems, true);
             }
             pw.println();
             pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb");
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 289ea1f..2a1b1db 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -190,6 +190,7 @@
     private static final int MSG_METERED_IFACES_CHANGED = 2;
     private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3;
     private static final int MSG_PROCESS_DIED = 4;
+    private static final int MSG_LIMIT_REACHED = 5;
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
@@ -225,8 +226,6 @@
 
     /** Set of currently active {@link Notification} tags. */
     private HashSet<String> mActiveNotifs = Sets.newHashSet();
-    /** Current values from {@link #setPolicyDataEnable(int, boolean)}. */
-    private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray();
 
     /** Foreground at both UID and PID granularity. */
     private SparseBooleanArray mUidForeground = new SparseBooleanArray();
@@ -424,19 +423,8 @@
             // only someone like NMS should be calling us
             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-            synchronized (mRulesLock) {
-                if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) {
-                    try {
-                        // force stats update to make sure we have numbers that
-                        // caused alert to trigger.
-                        mNetworkStats.forceUpdate();
-                    } catch (RemoteException e) {
-                        // ignored; service lives in system_server
-                    }
-
-                    updateNetworkEnabledLocked();
-                    updateNotificationsLocked();
-                }
+            if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
+                mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
             }
         }
     };
@@ -1481,6 +1469,25 @@
                     }
                     return true;
                 }
+                case MSG_LIMIT_REACHED: {
+                    final String iface = (String) msg.obj;
+
+                    synchronized (mRulesLock) {
+                        if (mMeteredIfaces.contains(iface)) {
+                            try {
+                                // force stats update to make sure we have
+                                // numbers that caused alert to trigger.
+                                mNetworkStats.forceUpdate();
+                            } catch (RemoteException e) {
+                                // ignored; service lives in system_server
+                            }
+
+                            updateNetworkEnabledLocked();
+                            updateNotificationsLocked();
+                        }
+                    }
+                    return true;
+                }
                 default: {
                     return false;
                 }
@@ -1519,21 +1526,13 @@
     }
 
     /**
-     * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)},
-     * dispatching only when actually changed.
+     * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
      */
     private void setPolicyDataEnable(int networkType, boolean enabled) {
-        synchronized (mActiveNetworkEnabled) {
-            final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true);
-            if (prevEnabled == enabled) return;
-
-            try {
-                mConnManager.setPolicyDataEnable(networkType, enabled);
-            } catch (RemoteException e) {
-                // ignored; service lives in system_server
-            }
-
-            mActiveNetworkEnabled.put(networkType, enabled);
+        try {
+            mConnManager.setPolicyDataEnable(networkType, enabled);
+        } catch (RemoteException e) {
+            // ignored; service lives in system_server
         }
     }
 
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 494c655..77b0d96 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -152,10 +152,6 @@
 
     private static final String TAG_NETSTATS_ERROR = "netstats_error";
 
-    private static final String DEV = "dev";
-    private static final String XT = "xt";
-    private static final String UID = "uid";
-
     private final Context mContext;
     private final INetworkManagementService mNetworkManager;
     private final IAlarmManager mAlarmManager;
@@ -278,6 +274,9 @@
             readNetworkXtStatsLocked();
         }
 
+        // bootstrap initial stats to prevent double-counting later
+        bootstrapStats();
+
         // watch for network interfaces to be claimed
         final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
@@ -311,9 +310,6 @@
         registerPollAlarmLocked();
         registerGlobalAlert();
 
-        // bootstrap initial stats to prevent double-counting later
-        bootstrapStats();
-
         mDropBox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
     }
 
@@ -837,9 +833,9 @@
 
         // persist when enough network data has occurred
         final long persistNetworkDevDelta = computeStatsDelta(
-                mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, DEV).getTotalBytes();
+                mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, "devp").getTotalBytes();
         final long persistNetworkXtDelta = computeStatsDelta(
-                mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, XT).getTotalBytes();
+                mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, "xtp").getTotalBytes();
         final boolean networkOverThreshold = persistNetworkDevDelta > threshold
                 || persistNetworkXtDelta > threshold;
         if (persistForce || (persistNetwork && networkOverThreshold)) {
@@ -851,7 +847,7 @@
 
         // persist when enough uid data has occurred
         final long persistUidDelta = computeStatsDelta(
-                mLastPersistUidSnapshot, uidSnapshot, true, UID).getTotalBytes();
+                mLastPersistUidSnapshot, uidSnapshot, true, "uidp").getTotalBytes();
         if (persistForce || (persistUid && persistUidDelta > threshold)) {
             writeUidStatsLocked();
             mLastPersistUidSnapshot = uidSnapshot;
@@ -880,7 +876,7 @@
         final HashSet<String> unknownIface = Sets.newHashSet();
 
         final NetworkStats delta = computeStatsDelta(
-                mLastPollNetworkDevSnapshot, networkDevSnapshot, false, DEV);
+                mLastPollNetworkDevSnapshot, networkDevSnapshot, false, "dev");
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -910,7 +906,7 @@
         final HashSet<String> unknownIface = Sets.newHashSet();
 
         final NetworkStats delta = computeStatsDelta(
-                mLastPollNetworkXtSnapshot, networkXtSnapshot, false, XT);
+                mLastPollNetworkXtSnapshot, networkXtSnapshot, false, "xt");
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -940,9 +936,9 @@
         ensureUidStatsLoadedLocked();
 
         final NetworkStats delta = computeStatsDelta(
-                mLastPollUidSnapshot, uidSnapshot, false, UID);
+                mLastPollUidSnapshot, uidSnapshot, false, "uid");
         final NetworkStats operationsDelta = computeStatsDelta(
-                mLastPollOperationsSnapshot, mOperations, false, UID);
+                mLastPollOperationsSnapshot, mOperations, false, "uidop");
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -971,8 +967,7 @@
         }
 
         mLastPollUidSnapshot = uidSnapshot;
-        mLastPollOperationsSnapshot = mOperations;
-        mOperations = new NetworkStats(0L, 10);
+        mLastPollOperationsSnapshot = mOperations.clone();
     }
 
     /**
@@ -1516,7 +1511,7 @@
 
                 // record error for debugging
                 final StringBuilder builder = new StringBuilder();
-                builder.append("found non-monotonic " + type + "values at left[" + e.leftIndex
+                builder.append("found non-monotonic " + type + " values at left[" + e.leftIndex
                         + "] - right[" + e.rightIndex + "]\n");
                 builder.append("left=").append(e.left).append('\n');
                 builder.append("right=").append(e.right).append('\n');
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index d2d2d8b..c2c6b4d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -478,8 +478,9 @@
     if (ns < 0)
         return BAD_VALUE;
 
-    if (ns == 0) {
-        ns = sensor->getSensor().getMinDelayNs();
+    nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
+    if (ns < minDelayNs) {
+        ns = minDelayNs;
     }
 
     if (ns < MINIMUM_EVENTS_PERIOD)
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8f4fdb8..1b00e93 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1217,23 +1217,25 @@
         sp<Client> client( static_cast<Client *>(s.client.get()) );
         transactionFlags |= setClientStateLocked(client, s.state);
     }
-    if (transactionFlags) {
-        setTransactionFlags(transactionFlags);
-    }
 
-    // if this is a synchronous transaction, wait for it to take effect before
-    // returning.
-    if (flags & eSynchronous) {
-        mTransationPending = true;
-    }
-    while (mTransationPending) {
-        status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-        if (CC_UNLIKELY(err != NO_ERROR)) {
-            // just in case something goes wrong in SF, return to the
-            // called after a few seconds.
-            LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
-            mTransationPending = false;
-            break;
+    if (transactionFlags) {
+        // this triggers the transaction
+        setTransactionFlags(transactionFlags);
+
+        // if this is a synchronous transaction, wait for it to take effect
+        // before returning.
+        if (flags & eSynchronous) {
+            mTransationPending = true;
+        }
+        while (mTransationPending) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                // just in case something goes wrong in SF, return to the
+                // called after a few seconds.
+                LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+                mTransationPending = false;
+                break;
+            }
         }
     }
 }
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 34f8848..f2ccb5b 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1513,14 +1513,65 @@
     static final int MIN_MATCH = 7;
 
     /**
-     * isEmergencyNumber: checks a given number against the list of
-     *   emergency numbers provided by the RIL and SIM card.
+     * Checks a given number against the list of
+     * emergency numbers provided by the RIL and SIM card.
      *
      * @param number the number to look up.
-     * @return if the number is in the list of emergency numbers
-     * listed in the ril / sim, then return true, otherwise false.
+     * @return true if the number is in the list of emergency numbers
+     *         listed in the RIL / SIM, otherwise return false.
      */
     public static boolean isEmergencyNumber(String number) {
+        // Return true only if the specified number *exactly* matches
+        // one of the emergency numbers listed by the RIL / SIM.
+        return isEmergencyNumberInternal(number, true /* useExactMatch */);
+    }
+
+    /**
+     * Checks if given number might *potentially* result in
+     * a call to an emergency service on the current network.
+     *
+     * Specifically, this method will return true if the specified number
+     * is an emergency number according to the list managed by the RIL or
+     * SIM, *or* if the specified number simply starts with the same
+     * digits as any of the emergency numbers listed in the RIL / SIM.
+     *
+     * This method is intended for internal use by the phone app when
+     * deciding whether to allow ACTION_CALL intents from 3rd party apps
+     * (where we're required to *not* allow emergency calls to be placed.)
+     *
+     * @param number the number to look up.
+     * @return true if the number is in the list of emergency numbers
+     *         listed in the RIL / SIM, *or* if the number starts with the
+     *         same digits as any of those emergency numbers.
+     *
+     * @hide
+     */
+    public static boolean isPotentialEmergencyNumber(String number) {
+        // Check against the emergency numbers listed by the RIL / SIM,
+        // and *don't* require an exact match.
+        return isEmergencyNumberInternal(number, false /* useExactMatch */);
+    }
+
+    /**
+     * Helper function for isEmergencyNumber(String) and
+     * isPotentialEmergencyNumber(String).
+     *
+     * @param number the number to look up.
+     *
+     * @param useExactMatch if true, consider a number to be an emergency
+     *           number only if it *exactly* matches a number listed in
+     *           the RIL / SIM.  If false, a number is considered to be an
+     *           emergency number if it simply starts with the same digits
+     *           as any of the emergency numbers listed in the RIL / SIM.
+     *           (Setting useExactMatch to false allows you to identify
+     *           number that could *potentially* result in emergency calls
+     *           since many networks will actually ignore trailing digits
+     *           after a valid emergency number.)
+     *
+     * @return true if the number is in the list of emergency numbers
+     *         listed in the RIL / sim, otherwise return false.
+     */
+    private static boolean isEmergencyNumberInternal(String number, boolean useExactMatch) {
         // If the number passed in is null, just return false:
         if (number == null) return false;
 
@@ -1540,16 +1591,26 @@
             // searches through the comma-separated list for a match,
             // return true if one is found.
             for (String emergencyNum : numbers.split(",")) {
-                if (number.startsWith(emergencyNum)) {
-                    return true;
+                if (useExactMatch) {
+                    if (number.equals(emergencyNum)) {
+                        return true;
+                    }
+                } else {
+                    if (number.startsWith(emergencyNum)) {
+                        return true;
+                    }
                 }
             }
             // no matches found against the list!
             return false;
         }
 
-        //no ecclist system property, so use our own list.
-        return (number.startsWith("112") || number.startsWith("911"));
+        // No ecclist system property, so use our own list.
+        if (useExactMatch) {
+            return (number.equals("112") || number.equals("911"));
+        } else {
+            return (number.startsWith("112") || number.startsWith("911"));
+        }
     }
 
     /**
@@ -1559,31 +1620,81 @@
      * @param defaultCountryIso the specific country which the number should be checked against
      * @return if the number is an emergency number for the specific country, then return true,
      * otherwise false
+     *
      * @hide
      */
     public static boolean isEmergencyNumber(String number, String defaultCountryIso) {
-      PhoneNumberUtil util = PhoneNumberUtil.getInstance();
-      try {
-        PhoneNumber pn = util.parse(number, defaultCountryIso);
-        // libphonenumber guarantees short numbers such as emergency numbers are classified as
-        // invalid. Therefore, if the number passes the validation test, we believe it is not an
-        // emergency number.
-        // TODO: Compare against a list of country-specific known emergency numbers instead, once
-        // that has been collected.
-        if (util.isValidNumber(pn)) {
-          return false;
-        } else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) {
-          // This is to prevent Brazilian local numbers which start with 911 being incorrectly
-          // classified as emergency numbers. 911 is not an emergency number in Brazil; it is also
-          // not possible to append additional digits to an emergency number to dial the number in
-          // Brazil - it won't connect.
-          // TODO: Clean this up once a list of country-specific known emergency numbers is
-          // collected.
-          return false;
+        return isEmergencyNumberInternal(number,
+                                         defaultCountryIso,
+                                         true /* useExactMatch */);
+    }
+
+    /**
+     * Checks if a given number might *potentially* result in a call to an
+     * emergency service, for a specific country.
+     *
+     * Specifically, this method will return true if the specified number
+     * is an emergency number in the specified country, *or* if the number
+     * simply starts with the same digits as any emergency number for that
+     * country.
+     *
+     * This method is intended for internal use by the phone app when
+     * deciding whether to allow ACTION_CALL intents from 3rd party apps
+     * (where we're required to *not* allow emergency calls to be placed.)
+     *
+     * @param number the number to look up.
+     * @param defaultCountryIso the specific country which the number should be checked against
+     * @return true if the number is an emergency number for the specific
+     *         country, *or* if the number starts with the same digits as
+     *         any of those emergency numbers.
+     *
+     * @hide
+     */
+    public static boolean isPotentialEmergencyNumber(String number, String defaultCountryIso) {
+        return isEmergencyNumberInternal(number,
+                                         defaultCountryIso,
+                                         false /* useExactMatch */);
+    }
+
+    /**
+     * Helper function for isEmergencyNumber(String, String) and
+     * isPotentialEmergencyNumber(String, String).
+     *
+     * @param number the number to look up.
+     * @param defaultCountryIso the specific country which the number should be checked against
+     * @param useExactMatch if true, consider a number to be an emergency
+     *           number only if it *exactly* matches a number listed in
+     *           the RIL / SIM.  If false, a number is considered to be an
+     *           emergency number if it simply starts with the same digits
+     *           as any of the emergency numbers listed in the RIL / SIM.
+     *
+     * @return true if the number is an emergency number for the specified country.
+     */
+    private static boolean isEmergencyNumberInternal(String number,
+                                                     String defaultCountryIso,
+                                                     boolean useExactMatch) {
+        PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+        try {
+            PhoneNumber pn = util.parse(number, defaultCountryIso);
+            // libphonenumber guarantees short numbers such as emergency numbers are classified as
+            // invalid. Therefore, if the number passes the validation test, we believe it is not an
+            // emergency number.
+            // TODO: Compare against a list of country-specific known emergency numbers instead, once
+            // that has been collected.
+            if (util.isValidNumber(pn)) {
+                return false;
+            } else if ("BR".equalsIgnoreCase(defaultCountryIso) && number.length() >= 8) {
+                // This is to prevent Brazilian local numbers which start with 911 being incorrectly
+                // classified as emergency numbers. 911 is not an emergency number in Brazil; it is also
+                // not possible to append additional digits to an emergency number to dial the number in
+                // Brazil - it won't connect.
+                // TODO: Clean this up once a list of country-specific known emergency numbers is
+                // collected.
+                return false;
+            }
+        } catch (NumberParseException e) {
         }
-      } catch (NumberParseException e) {
-      }
-      return isEmergencyNumber(number);
+        return isEmergencyNumberInternal(number, useExactMatch);
     }
 
     /**
@@ -1592,12 +1703,66 @@
      *
      * @param number the number to look up.
      * @param context the specific context which the number should be checked against
-     * @return if a phone number is an emergency number for a local country, based on the
-     * CountryDetector.
+     * @return true if the specified number is an emergency number for a local country, based on the
+     *              CountryDetector.
+     *
      * @see android.location.CountryDetector
      * @hide
      */
     public static boolean isLocalEmergencyNumber(String number, Context context) {
+        return isLocalEmergencyNumberInternal(number,
+                                              context,
+                                              true /* useExactMatch */);
+    }
+
+    /**
+     * Checks if a given number might *potentially* result in a call to an
+     * emergency service, for the country that the user is in. The current
+     * country is determined using the CountryDetector.
+     *
+     * Specifically, this method will return true if the specified number
+     * is an emergency number in the current country, *or* if the number
+     * simply starts with the same digits as any emergency number for the
+     * current country.
+     *
+     * This method is intended for internal use by the phone app when
+     * deciding whether to allow ACTION_CALL intents from 3rd party apps
+     * (where we're required to *not* allow emergency calls to be placed.)
+     *
+     * @param number the number to look up.
+     * @param context the specific context which the number should be checked against
+     * @return true if the specified number is an emergency number for a local country, based on the
+     *              CountryDetector.
+     *
+     * @see android.location.CountryDetector
+     * @hide
+     */
+    public static boolean isPotentialLocalEmergencyNumber(String number, Context context) {
+        return isLocalEmergencyNumberInternal(number,
+                                              context,
+                                              false /* useExactMatch */);
+    }
+
+    /**
+     * Helper function for isLocalEmergencyNumber() and
+     * isPotentialLocalEmergencyNumber().
+     *
+     * @param number the number to look up.
+     * @param context the specific context which the number should be checked against
+     * @param useExactMatch if true, consider a number to be an emergency
+     *           number only if it *exactly* matches a number listed in
+     *           the RIL / SIM.  If false, a number is considered to be an
+     *           emergency number if it simply starts with the same digits
+     *           as any of the emergency numbers listed in the RIL / SIM.
+     *
+     * @return true if the specified number is an emergency number for a
+     *              local country, based on the CountryDetector.
+     *
+     * @see android.location.CountryDetector
+     */
+    private static boolean isLocalEmergencyNumberInternal(String number,
+                                                          Context context,
+                                                          boolean useExactMatch) {
         String countryIso;
         CountryDetector detector = (CountryDetector) context.getSystemService(
                 Context.COUNTRY_DETECTOR);
@@ -1609,7 +1774,7 @@
             Log.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: "
                     + countryIso);
         }
-        return isEmergencyNumber(number, countryIso);
+        return isEmergencyNumberInternal(number, countryIso, useExactMatch);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index fc8a145..1410747 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -291,12 +291,31 @@
         // flexibly...
 
         int limit;
-        if (ted.msgCount > 1) {
-            limit = (ted.codeUnitSize == ENCODING_7BIT) ?
-                MAX_USER_DATA_SEPTETS_WITH_HEADER : MAX_USER_DATA_BYTES_WITH_HEADER;
+        if (ted.codeUnitSize == ENCODING_7BIT) {
+            int udhLength;
+            if (ted.languageTable != 0 && ted.languageShiftTable != 0) {
+                udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES;
+            } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) {
+                udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE;
+            } else {
+                udhLength = 0;
+            }
+
+            if (ted.msgCount > 1) {
+                udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE;
+            }
+
+            if (udhLength != 0) {
+                udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH;
+            }
+
+            limit = MAX_USER_DATA_SEPTETS - udhLength;
         } else {
-            limit = (ted.codeUnitSize == ENCODING_7BIT) ?
-                MAX_USER_DATA_SEPTETS : MAX_USER_DATA_BYTES;
+            if (ted.msgCount > 1) {
+                limit = MAX_USER_DATA_BYTES_WITH_HEADER;
+            } else {
+                limit = MAX_USER_DATA_BYTES;
+            }
         }
 
         int pos = 0;  // Index in code units.
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 5b13603..410e961 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -167,7 +167,9 @@
     // independent of mInternalDataEnabled and requests for APN access
     // persisted
     protected boolean mUserDataEnabled = true;
-    protected boolean mPolicyDataEnabled = true;
+
+    // TODO: move away from static state once 5587429 is fixed.
+    protected static boolean sPolicyDataEnabled = true;
 
     private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
 
@@ -766,7 +768,7 @@
     public boolean getAnyDataEnabled() {
         final boolean result;
         synchronized (mDataEnabledLock) {
-            result = (mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled
+            result = (mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled
                     && (enabledCount != 0));
         }
         if (!result && DBG) log("getAnyDataEnabled " + result);
@@ -1132,8 +1134,8 @@
     protected void onSetPolicyDataEnabled(boolean enabled) {
         synchronized (mDataEnabledLock) {
             final boolean prevEnabled = getAnyDataEnabled();
-            if (mPolicyDataEnabled != enabled) {
-                mPolicyDataEnabled = enabled;
+            if (sPolicyDataEnabled != enabled) {
+                sPolicyDataEnabled = enabled;
                 if (prevEnabled != getAnyDataEnabled()) {
                     if (!prevEnabled) {
                         resetAllRetryCounts();
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 2e99849..25647ac 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -60,25 +60,25 @@
      * all combinations of header elements below will have at least one free bit
      * when padding to the nearest septet boundary.
      */
-    private static final int UDH_SEPTET_COST_LENGTH = 1;
+    public static final int UDH_SEPTET_COST_LENGTH = 1;
 
     /**
      * Using a non-default language locking shift table OR single shift table
      * requires a user data header of 3 octets, or 4 septets, plus UDH length.
      */
-    private static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4;
+    public static final int UDH_SEPTET_COST_ONE_SHIFT_TABLE = 4;
 
     /**
      * Using a non-default language locking shift table AND single shift table
      * requires a user data header of 6 octets, or 7 septets, plus UDH length.
      */
-    private static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7;
+    public static final int UDH_SEPTET_COST_TWO_SHIFT_TABLES = 7;
 
     /**
      * Multi-part messages require a user data header of 5 octets, or 6 septets,
      * plus UDH length.
      */
-    private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
+    public static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
 
     /**
      * Converts a char to a GSM 7 bit table index.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 865caf6..7cd01a1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -549,7 +549,7 @@
     @Override
     public boolean getAnyDataEnabled() {
         synchronized (mDataEnabledLock) {
-            if (!(mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled)) return false;
+            if (!(mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled)) return false;
             for (ApnContext apnContext : mApnContexts.values()) {
                 // Make sure we dont have a context that going down
                 // and is explicitly disabled.
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
index 41a719e..5950669 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
@@ -16,11 +16,14 @@
 
 package com.android.internal.telephony;
 
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
 import com.android.internal.telephony.gsm.SmsMessage;
 import com.android.internal.util.HexDump;
 
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import java.util.ArrayList;
 
 public class GsmSmsTest extends AndroidTestCase {
 
@@ -232,6 +235,110 @@
     };
 
     @SmallTest
+    public void testFragmentText() throws Exception {
+        boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() ==
+                TelephonyManager.PHONE_TYPE_GSM);
+
+        // Valid 160 character 7-bit text.
+        String text = "123456789012345678901234567890123456789012345678901234567890" +
+                "1234567890123456789012345678901234567890123456789012345678901234567890" +
+                "123456789012345678901234567890";
+        SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false);
+        assertEquals(1, ted.msgCount);
+        assertEquals(160, ted.codeUnitCount);
+        assertEquals(1, ted.codeUnitSize);
+        assertEquals(0, ted.languageTable);
+        assertEquals(0, ted.languageShiftTable);
+        if (isGsmPhone) {
+            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+            assertEquals(1, fragments.size());
+        }
+
+        // Valid 161 character 7-bit text.
+        text = "123456789012345678901234567890123456789012345678901234567890" +
+                "1234567890123456789012345678901234567890123456789012345678901234567890" +
+                "1234567890123456789012345678901";
+        ted = SmsMessage.calculateLength(text, false);
+        assertEquals(2, ted.msgCount);
+        assertEquals(161, ted.codeUnitCount);
+        assertEquals(1, ted.codeUnitSize);
+        assertEquals(0, ted.languageTable);
+        assertEquals(0, ted.languageShiftTable);
+        if (isGsmPhone) {
+            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+            assertEquals(2, fragments.size());
+            assertEquals(text, fragments.get(0) + fragments.get(1));
+            assertEquals(153, fragments.get(0).length());
+            assertEquals(8, fragments.get(1).length());
+        }
+    }
+
+    @SmallTest
+    public void testFragmentTurkishText() throws Exception {
+        boolean isGsmPhone = (TelephonyManager.getDefault().getPhoneType() ==
+                TelephonyManager.PHONE_TYPE_GSM);
+
+        int[] oldTables = GsmAlphabet.getEnabledSingleShiftTables();
+        int[] turkishTable = { 1 };
+        GsmAlphabet.setEnabledSingleShiftTables(turkishTable);
+
+        // Valid 77 character text with Turkish characters.
+        String text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" +
+                "ĞŞİğşıĞŞİğşıĞŞİğş";
+        SmsMessageBase.TextEncodingDetails ted = SmsMessage.calculateLength(text, false);
+        assertEquals(1, ted.msgCount);
+        assertEquals(154, ted.codeUnitCount);
+        assertEquals(1, ted.codeUnitSize);
+        assertEquals(0, ted.languageTable);
+        assertEquals(1, ted.languageShiftTable);
+        if (isGsmPhone) {
+            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+            assertEquals(1, fragments.size());
+            assertEquals(text, fragments.get(0));
+            assertEquals(77, fragments.get(0).length());
+        }
+
+        // Valid 78 character text with Turkish characters.
+        text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" +
+                "ĞŞİğşıĞŞİğşıĞŞİğşı";
+        ted = SmsMessage.calculateLength(text, false);
+        assertEquals(2, ted.msgCount);
+        assertEquals(156, ted.codeUnitCount);
+        assertEquals(1, ted.codeUnitSize);
+        assertEquals(0, ted.languageTable);
+        assertEquals(1, ted.languageShiftTable);
+        if (isGsmPhone) {
+            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+            assertEquals(2, fragments.size());
+            assertEquals(text, fragments.get(0) + fragments.get(1));
+            assertEquals(74, fragments.get(0).length());
+            assertEquals(4, fragments.get(1).length());
+        }
+
+        // Valid 160 character text with Turkish characters.
+        text = "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı" +
+                "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğ" +
+                "ĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşıĞŞİğşı";
+        ted = SmsMessage.calculateLength(text, false);
+        assertEquals(3, ted.msgCount);
+        assertEquals(320, ted.codeUnitCount);
+        assertEquals(1, ted.codeUnitSize);
+        assertEquals(0, ted.languageTable);
+        assertEquals(1, ted.languageShiftTable);
+        if (isGsmPhone) {
+            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text);
+            assertEquals(3, fragments.size());
+            assertEquals(text, fragments.get(0) + fragments.get(1) + fragments.get(2));
+            assertEquals(74, fragments.get(0).length());
+            assertEquals(74, fragments.get(1).length());
+            assertEquals(12, fragments.get(2).length());
+        }
+
+        GsmAlphabet.setEnabledSingleShiftTables(oldTables);
+    }
+
+
+    @SmallTest
     public void testDecode() throws Exception {
         decodeSingle(0);    // default table
         decodeSingle(1);    // Turkish locking shift table
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index e2349af..d34a7c5 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -550,21 +550,51 @@
     }
     @SmallTest
     public void testIsEmergencyNumber() {
-      assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US"));
-      assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US"));
-      // The next two numbers are not valid phone numbers in the US, but can be used to trick the
-      // system to dial 911 and 112, which are emergency numbers in the US. For the purpose of
-      // addressing that, they are also classified as emergency numbers in the US.
-      assertTrue(PhoneNumberUtils.isEmergencyNumber("91112345", "US"));
-      assertTrue(PhoneNumberUtils.isEmergencyNumber("11212345", "US"));
-      // A valid mobile phone number from Singapore shouldn't be classified as an emergency number
-      // in Singapore, as 911 is not an emergency number there.
-      assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG"));
-      // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
-      // in Brazil, as 112 is not an emergency number there.
-      assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR"));
-      // A valid local phone number from Brazil shouldn't be classified as an emergency number in
-      // Brazil.
-      assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR"));
+        // There are two parallel sets of tests here: one for the
+        // regular isEmergencyNumber() method, and the other for
+        // isPotentialEmergencyNumber().
+        //
+        // (The difference is that isEmergencyNumber() will return true
+        // only if the specified number exactly matches an actual
+        // emergency number, but isPotentialEmergencyNumber() will
+        // return true if the specified number simply starts with the
+        // same digits as any actual emergency number.)
+
+        // Tests for isEmergencyNumber():
+        assertTrue(PhoneNumberUtils.isEmergencyNumber("911", "US"));
+        assertTrue(PhoneNumberUtils.isEmergencyNumber("112", "US"));
+        // The next two numbers are not valid phone numbers in the US,
+        // so do not count as emergency numbers (but they *are* "potential"
+        // emergency numbers; see below.)
+        assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "US"));
+        assertFalse(PhoneNumberUtils.isEmergencyNumber("11212345", "US"));
+        // A valid mobile phone number from Singapore shouldn't be classified as an emergency number
+        // in Singapore, as 911 is not an emergency number there.
+        assertFalse(PhoneNumberUtils.isEmergencyNumber("91121234", "SG"));
+        // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
+        // in Brazil, as 112 is not an emergency number there.
+        assertFalse(PhoneNumberUtils.isEmergencyNumber("1121234567", "BR"));
+        // A valid local phone number from Brazil shouldn't be classified as an emergency number in
+        // Brazil.
+        assertFalse(PhoneNumberUtils.isEmergencyNumber("91112345", "BR"));
+
+        // Tests for isPotentialEmergencyNumber():
+        // These first two are obviously emergency numbers:
+        assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("911", "US"));
+        assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("112", "US"));
+        // The next two numbers are not valid phone numbers in the US, but can be used to trick the
+        // system to dial 911 and 112, which are emergency numbers in the US. For the purpose of
+        // addressing that, they are also classified as "potential" emergency numbers in the US.
+        assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "US"));
+        assertTrue(PhoneNumberUtils.isPotentialEmergencyNumber("11212345", "US"));
+        // A valid mobile phone number from Singapore shouldn't be classified as an emergency number
+        // in Singapore, as 911 is not an emergency number there.
+        assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91121234", "SG"));
+        // A valid fixed-line phone number from Brazil shouldn't be classified as an emergency number
+        // in Brazil, as 112 is not an emergency number there.
+        assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("1121234567", "BR"));
+        // A valid local phone number from Brazil shouldn't be classified as an emergency number in
+        // Brazil.
+        assertFalse(PhoneNumberUtils.isPotentialEmergencyNumber("91112345", "BR"));
     }
 }
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 22eb579..175f227 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -45,6 +46,7 @@
 public class FrameworkPerfActivity extends Activity
         implements AdapterView.OnItemSelectedListener {
     static final String TAG = "Perf";
+    static final boolean DEBUG = false;
 
     Spinner mFgSpinner;
     Spinner mBgSpinner;
@@ -67,22 +69,47 @@
     TestService.Op mBgTest;
     int mCurOpIndex = 0;
     TestConnection mCurConnection;
+    boolean mConnectionBound;
 
     final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
 
-    class TestConnection implements ServiceConnection {
+    class TestConnection implements ServiceConnection, IBinder.DeathRecipient {
         Messenger mService;
+        boolean mLinked;
 
         @Override public void onServiceConnected(ComponentName name, IBinder service) {
-            mService = new Messenger(service);
-            dispatchCurOp(this);
+            try {
+                if (!(service instanceof Binder)) {
+                    // If remote, we'll be killing ye.
+                    service.linkToDeath(this, 0);
+                    mLinked = true;
+                }
+                mService = new Messenger(service);
+                dispatchCurOp(this);
+            } catch (RemoteException e) {
+                // Whoops, service has disappeared...  try starting again.
+                Log.w(TAG, "Test service died, starting again");
+                startCurOp();
+            }
         }
 
         @Override public void onServiceDisconnected(ComponentName name) {
         }
+
+        @Override public void binderDied() {
+            cleanup();
+            connectionDied(this);
+        }
+
+        void cleanup() {
+            if (mLinked) {
+                mLinked = false;
+                mService.getBinder().unlinkToDeath(this, 0);
+            }
+        }
     }
 
-    static final int MSG_CONTINUE = 1000;
+    static final int MSG_DO_NEXT_TEST = 1000;
 
     final Handler mHandler = new Handler() {
         @Override public void handleMessage(Message msg) {
@@ -93,11 +120,7 @@
                     RunResult res = (RunResult)bundle.getParcelable("res");
                     completeCurOp(res);
                 } break;
-                case TestService.RES_TERMINATED: {
-                    // Give a little time for things to settle down.
-                    sendMessageDelayed(obtainMessage(MSG_CONTINUE), 500);
-                } break;
-                case MSG_CONTINUE: {
+                case MSG_DO_NEXT_TEST: {
                     startCurOp();
                 } break;
             }
@@ -235,7 +258,7 @@
         try {
             conn.mService.send(msg);
         } catch (RemoteException e) {
-            Log.i(TAG, "Failure communicating with service", e);
+            Log.w(TAG, "Failure communicating with service", e);
         }
     }
 
@@ -273,29 +296,55 @@
     }
 
     void disconnect() {
-        if (mCurConnection != null) {
-            unbindService(mCurConnection);
-            if (mCurConnection.mService != null) {
+        final TestConnection conn = mCurConnection;
+        if (conn != null) {
+            if (DEBUG) {
+                RuntimeException here = new RuntimeException("here");
+                here.fillInStackTrace();
+                Log.i(TAG, "Unbinding " + conn, here);
+            }
+            if (mConnectionBound) {
+                unbindService(conn);
+                mConnectionBound = false;
+            }
+            if (conn.mLinked) {
                 Message msg = Message.obtain(null, TestService.CMD_TERMINATE);
-                msg.replyTo = mMessenger;
                 try {
-                    mCurConnection.mService.send(msg);
+                    conn.mService.send(msg);
+                    return;
                 } catch (RemoteException e) {
-                    Log.i(TAG, "Failure communicating with service", e);
+                    Log.w(TAG, "Test service aleady died when terminating");
                 }
             }
+            conn.cleanup();
+        }
+        connectionDied(conn);
+    }
+
+    void connectionDied(TestConnection conn) {
+        if (mCurConnection == conn) {
+            // Now that we know the test process has died, we can commence
+            // the next test.  Just give a little delay to allow the activity
+            // manager to know it has died as well (not a disaster if it hasn't
+            // yet, though).
+            if (mConnectionBound) {
+                unbindService(conn);
+            }
             mCurConnection = null;
+            mHandler.sendMessageDelayed(Message.obtain(null, MSG_DO_NEXT_TEST), 100);
         }
     }
 
     void startCurOp() {
+        if (DEBUG) Log.i(TAG, "startCurOp: mCurConnection=" + mCurConnection);
         if (mCurConnection != null) {
             disconnect();
+            return;
         }
         if (mStarted) {
             mHandler.removeMessages(TestService.RES_TEST_FINISHED);
             mHandler.removeMessages(TestService.RES_TERMINATED);
-            mHandler.removeMessages(MSG_CONTINUE);
+            mHandler.removeMessages(MSG_DO_NEXT_TEST);
             mCurConnection = new TestConnection();
             Intent intent;
             if (mLocalCheckBox.isChecked()) {
@@ -303,7 +352,13 @@
             } else {
                 intent = new Intent(this, TestService.class);
             }
+            if (DEBUG) {
+                RuntimeException here = new RuntimeException("here");
+                here.fillInStackTrace();
+                Log.i(TAG, "Binding " + mCurConnection, here);
+            }
             bindService(intent, mCurConnection, BIND_AUTO_CREATE|BIND_IMPORTANT);
+            mConnectionBound = true;
         }
     }
 
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
index ce27b65..3d939bd 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
@@ -138,7 +138,10 @@
 
     static final int CMD_START_TEST = 1;
     static final int CMD_TERMINATE = 2;
-    
+
+    static final int MSG_REALLY_START = 1000;
+    static final int MSG_REALLY_TERMINATE = 1001;
+
     static final int RES_TEST_FINISHED = 1;
     static final int RES_TERMINATED = 2;
 
@@ -146,6 +149,13 @@
         @Override public void handleMessage(Message msg) {
             switch (msg.what) {
                 case CMD_START_TEST: {
+                    // Give a little time for things to settle down.
+                    Message newMsg = Message.obtain(null, MSG_REALLY_START);
+                    newMsg.obj = msg.obj;
+                    newMsg.replyTo = msg.replyTo;
+                    sendMessageDelayed(newMsg, 500);
+                } break;
+                case MSG_REALLY_START: {
                     Bundle bundle = (Bundle)msg.obj;
                     bundle.setClassLoader(getClassLoader());
                     final TestArgs args = (TestArgs)bundle.getParcelable("args");
@@ -166,6 +176,13 @@
                     });
                 } break;
                 case CMD_TERMINATE: {
+                    // Give a little time for things to settle down.
+                    Message newMsg = Message.obtain(null, MSG_REALLY_TERMINATE);
+                    newMsg.obj = msg.obj;
+                    newMsg.replyTo = msg.replyTo;
+                    sendMessageDelayed(newMsg, 50);
+                } break;
+                case MSG_REALLY_TERMINATE: {
                     if (msg.replyTo != null) {
                         Message reply = Message.obtain(null, RES_TERMINATED);
                         try {
@@ -174,7 +191,7 @@
                         }
                     }
                     terminate();
-                }
+                } break;
             }
         }
     };
@@ -187,7 +204,7 @@
     }
 
     void terminate() {
-        Process.killProcess(Process.myPid());
+        Runtime.getRuntime().exit(0);
     }
 
     enum BackgroundMode {
diff --git a/wifi/java/android/net/wifi/WifiApConfigStore.java b/wifi/java/android/net/wifi/WifiApConfigStore.java
index bb5427d..0531ca3 100644
--- a/wifi/java/android/net/wifi/WifiApConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiApConfigStore.java
@@ -19,11 +19,16 @@
 import android.content.Context;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.os.Environment;
-import android.os.Message;
 import android.os.Handler;
-import android.os.HandlerThread;
+import android.os.Message;
+import android.os.Messenger;
 import android.util.Log;
 
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.R;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.DataInputStream;
@@ -34,16 +39,13 @@
 import java.net.InetAddress;
 import java.util.UUID;
 
-import com.android.internal.R;
-
-
 /**
  * Provides API to the WifiStateMachine for doing read/write access
  * to soft access point configuration
  */
-class WifiApConfigStore {
+class WifiApConfigStore extends StateMachine {
 
-    private static Context sContext;
+    private Context mContext;
     private static final String TAG = "WifiApConfigStore";
 
     private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
@@ -51,131 +53,160 @@
 
     private static final int AP_CONFIG_FILE_VERSION = 1;
 
-    private static WifiConfiguration sApConfig = new WifiConfiguration();
-    private static final Object sApConfigLock = new Object();
+    private State mDefaultState = new DefaultState();
+    private State mInactiveState = new InactiveState();
+    private State mActiveState = new ActiveState();
 
-    private static FileReadWriteHandler sFileReadWriteHandler;
-    private static final int READ_AP_CONFIG               = 1;
-    private static final int WRITE_AP_CONFIG              = 2;
+    private WifiConfiguration mWifiApConfig = null;
+    private AsyncChannel mReplyChannel = new AsyncChannel();
 
-    static void initialize(Context context) {
-        sContext = context;
+    WifiApConfigStore(Context context, Handler target) {
+        super(TAG, target.getLooper());
 
-        /* File operations happen on a seperate thread */
-        HandlerThread configThread = new HandlerThread("WifiApConfigStore");
-        configThread.start();
-        sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper());
-        Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget();
+        mContext = context;
+        addState(mDefaultState);
+            addState(mInactiveState, mDefaultState);
+            addState(mActiveState, mDefaultState);
+
+        setInitialState(mInactiveState);
     }
 
-
-    static void setApConfiguration(WifiConfiguration config) {
-        synchronized (sApConfigLock) {
-            sApConfig = config;
-        }
-        Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config))
-            .sendToTarget();
+    public static WifiApConfigStore makeWifiApConfigStore(Context context, Handler target) {
+        WifiApConfigStore s = new WifiApConfigStore(context, target);
+        s.start();
+        return s;
     }
 
-    static WifiConfiguration getApConfiguration() {
-        synchronized (sApConfigLock) {
-            return new WifiConfiguration(sApConfig);
-        }
-    }
-
-    /**
-     * File read/write handler
-     */
-    private static class FileReadWriteHandler extends Handler {
-
-        public FileReadWriteHandler(android.os.Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case WRITE_AP_CONFIG:
-                    writeApConfiguration((WifiConfiguration) msg.obj);
+    class DefaultState extends State {
+        public boolean processMessage(Message message) {
+            switch (message.what) {
+                case WifiStateMachine.CMD_SET_AP_CONFIG:
+                case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
+                    Log.e(TAG, "Unexpected message: " + message);
                     break;
-                case READ_AP_CONFIG:
-                    readApConfiguration();
+                case WifiStateMachine.CMD_REQUEST_AP_CONFIG:
+                    mReplyChannel.replyToMessage(message,
+                            WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);
                     break;
                 default:
-                    Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg);
+                    Log.e(TAG, "Failed to handle " + message);
                     break;
             }
+            return HANDLED;
         }
+    }
 
-        private static void writeApConfiguration(final WifiConfiguration config) {
-            DataOutputStream out = null;
-            try {
-                out = new DataOutputStream(new BufferedOutputStream(
-                            new FileOutputStream(AP_CONFIG_FILE)));
-
-                out.writeInt(AP_CONFIG_FILE_VERSION);
-                out.writeUTF(config.SSID);
-                int authType = config.getAuthType();
-                out.writeInt(authType);
-                if(authType != KeyMgmt.NONE) {
-                    out.writeUTF(config.preSharedKey);
-                }
-            } catch (IOException e) {
-                Log.e(TAG, "Error writing hotspot configuration" + e);
-            } finally {
-                if (out != null) {
-                    try {
-                        out.close();
-                    } catch (IOException e) {}
-                }
+    class InactiveState extends State {
+        public boolean processMessage(Message message) {
+            switch (message.what) {
+                case WifiStateMachine.CMD_SET_AP_CONFIG:
+                    mWifiApConfig = (WifiConfiguration) message.obj;
+                    transitionTo(mActiveState);
+                    break;
+                default:
+                    return NOT_HANDLED;
             }
+            return HANDLED;
+        }
+    }
+
+    class ActiveState extends State {
+        public void enter() {
+            new Thread(new Runnable() {
+                public void run() {
+                    writeApConfiguration(mWifiApConfig);
+                    sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);
+                }
+            }).start();
         }
 
-        private static void readApConfiguration() {
-            DataInputStream in = null;
-            try {
-                WifiConfiguration config = new WifiConfiguration();
-                in = new DataInputStream(new BufferedInputStream(new FileInputStream(
-                                AP_CONFIG_FILE)));
-
-                int version = in.readInt();
-                if (version != 1) {
-                    Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
-                    setDefaultApConfiguration();
-                    return;
-                }
-                config.SSID = in.readUTF();
-                int authType = in.readInt();
-                config.allowedKeyManagement.set(authType);
-                if (authType != KeyMgmt.NONE) {
-                    config.preSharedKey = in.readUTF();
-                }
-                synchronized (sApConfigLock) {
-                    sApConfig = config;
-                }
-            } catch (IOException ignore) {
-                setDefaultApConfiguration();
-            } finally {
-                if (in != null) {
-                    try {
-                        in.close();
-                    } catch (IOException e) {}
-                }
+        public boolean processMessage(Message message) {
+            switch (message.what) {
+                //TODO: have feedback to the user when we do this
+                //to indicate the write is currently in progress
+                case WifiStateMachine.CMD_SET_AP_CONFIG:
+                    deferMessage(message);
+                    break;
+                case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
+                    transitionTo(mInactiveState);
+                    break;
+                default:
+                    return NOT_HANDLED;
             }
+            return HANDLED;
         }
+    }
 
-        /* Generate a default WPA2 based configuration with a random password.
-           We are changing the Wifi Ap configuration storage from secure settings to a
-           flat file accessible only by the system. A WPA2 based default configuration
-           will keep the device secure after the update */
-        private static void setDefaultApConfiguration() {
+    void loadApConfiguration() {
+        DataInputStream in = null;
+        try {
             WifiConfiguration config = new WifiConfiguration();
-            config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default);
-            config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
-            String randomUUID = UUID.randomUUID().toString();
-            //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
-            config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
-            setApConfiguration(config);
+            in = new DataInputStream(new BufferedInputStream(new FileInputStream(
+                            AP_CONFIG_FILE)));
+
+            int version = in.readInt();
+            if (version != 1) {
+                Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
+                setDefaultApConfiguration();
+                return;
+            }
+            config.SSID = in.readUTF();
+            int authType = in.readInt();
+            config.allowedKeyManagement.set(authType);
+            if (authType != KeyMgmt.NONE) {
+                config.preSharedKey = in.readUTF();
+            }
+            mWifiApConfig = config;
+        } catch (IOException ignore) {
+            setDefaultApConfiguration();
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {}
+            }
         }
     }
+
+    Messenger getMessenger() {
+        return new Messenger(getHandler());
+    }
+
+    private void writeApConfiguration(final WifiConfiguration config) {
+        DataOutputStream out = null;
+        try {
+            out = new DataOutputStream(new BufferedOutputStream(
+                        new FileOutputStream(AP_CONFIG_FILE)));
+
+            out.writeInt(AP_CONFIG_FILE_VERSION);
+            out.writeUTF(config.SSID);
+            int authType = config.getAuthType();
+            out.writeInt(authType);
+            if(authType != KeyMgmt.NONE) {
+                out.writeUTF(config.preSharedKey);
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Error writing hotspot configuration" + e);
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {}
+            }
+        }
+    }
+
+    /* Generate a default WPA2 based configuration with a random password.
+       We are changing the Wifi Ap configuration storage from secure settings to a
+       flat file accessible only by the system. A WPA2 based default configuration
+       will keep the device secure after the update */
+    private void setDefaultApConfiguration() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
+        config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+        String randomUUID = UUID.randomUUID().toString();
+        //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+        config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
+        sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config);
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 00fae2e..aadcaad 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -184,6 +184,7 @@
     private WifiP2pManager mWifiP2pManager;
     //Used to initiate a connection with WifiP2pService
     private AsyncChannel mWifiP2pChannel = new AsyncChannel();
+    private AsyncChannel mWifiApConfigChannel = new AsyncChannel();
 
     // Event log tags (must be in sync with event-log-tags)
     private static final int EVENTLOG_WIFI_STATE_CHANGED        = 50021;
@@ -233,12 +234,16 @@
     static final int CMD_STOP_AP                          = BASE + 24;
     /* Set the soft access point configuration */
     static final int CMD_SET_AP_CONFIG                    = BASE + 25;
-    /* Get the soft access point configuration */
-    static final int CMD_GET_AP_CONFIG                    = BASE + 26;
+    /* Soft access point configuration set completed */
+    static final int CMD_SET_AP_CONFIG_COMPLETED          = BASE + 26;
+    /* Request the soft access point configuration */
+    static final int CMD_REQUEST_AP_CONFIG                = BASE + 27;
+    /* Response to access point configuration request */
+    static final int CMD_RESPONSE_AP_CONFIG               = BASE + 28;
     /* Set configuration on tether interface */
-    static final int CMD_TETHER_INTERFACE                 = BASE + 27;
+    static final int CMD_TETHER_INTERFACE                 = BASE + 29;
 
-    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 28;
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 30;
 
     /* Supplicant commands */
     /* Is supplicant alive ? */
@@ -530,6 +535,11 @@
         mWpsStateMachine = new WpsStateMachine(context, this, getHandler());
         mLinkProperties = new LinkProperties();
 
+        WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
+                context, getHandler());
+        wifiApConfigStore.loadApConfiguration();
+        mWifiApConfigChannel.connectSync(mContext, getHandler(), wifiApConfigStore.getMessenger());
+
         mNetworkInfo.setIsAvailable(false);
         mLinkProperties.clear();
         mLastBssid = null;
@@ -659,11 +669,11 @@
     }
 
     public void setWifiApConfiguration(WifiConfiguration config) {
-        sendMessage(obtainMessage(CMD_SET_AP_CONFIG, config));
+        mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
     }
 
-    public WifiConfiguration syncGetWifiApConfiguration(AsyncChannel channel) {
-        Message resultMsg = channel.sendMessageSynchronously(CMD_GET_AP_CONFIG);
+    public WifiConfiguration syncGetWifiApConfiguration() {
+        Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG);
         WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
         resultMsg.recycle();
         return ret;
@@ -1714,25 +1724,27 @@
      * TODO: Add control channel setup through hostapd that allows changing config
      * on a running daemon
      */
-    private boolean startSoftApWithConfig(WifiConfiguration config) {
-        if (config == null) {
-            config = WifiApConfigStore.getApConfiguration();
-        } else {
-            WifiApConfigStore.setApConfiguration(config);
-        }
-        try {
-            mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
-        } catch (Exception e) {
-            loge("Exception in softap start " + e);
-            try {
-                mNwService.stopAccessPoint(mInterfaceName);
-                mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
-            } catch (Exception e1) {
-                loge("Exception in softap re-start " + e1);
-                return false;
+    private void startSoftApWithConfig(final WifiConfiguration config) {
+        // start hostapd on a seperate thread
+        new Thread(new Runnable() {
+            public void run() {
+                try {
+                    mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+                } catch (Exception e) {
+                    loge("Exception in softap start " + e);
+                    try {
+                        mNwService.stopAccessPoint(mInterfaceName);
+                        mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+                    } catch (Exception e1) {
+                        loge("Exception in softap re-start " + e1);
+                        sendMessage(CMD_START_AP_FAILURE);
+                        return;
+                    }
+                }
+                if (DBG) log("Soft AP start successful");
+                sendMessage(CMD_START_AP_SUCCESS);
             }
-        }
-        return true;
+        }).start();
     }
 
     /********************************************************
@@ -1775,13 +1787,6 @@
                 case CMD_ENABLE_BACKGROUND_SCAN:
                     mEnableBackgroundScan = (message.arg1 == 1);
                     break;
-                case CMD_SET_AP_CONFIG:
-                    WifiApConfigStore.setApConfiguration((WifiConfiguration) message.obj);
-                    break;
-                case CMD_GET_AP_CONFIG:
-                    WifiConfiguration config = WifiApConfigStore.getApConfiguration();
-                    mReplyChannel.replyToMessage(message, message.what, config);
-                    break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
                 case CMD_UNLOAD_DRIVER:
@@ -1823,6 +1828,11 @@
                 case CMD_ENABLE_ALL_NETWORKS:
                 case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+                /* Handled by WifiApConfigStore */
+                case CMD_SET_AP_CONFIG:
+                case CMD_SET_AP_CONFIG_COMPLETED:
+                case CMD_REQUEST_AP_CONFIG:
+                case CMD_RESPONSE_AP_CONFIG:
                     break;
                 case WifiMonitor.DRIVER_HUNG_EVENT:
                     setWifiEnabled(false);
@@ -1856,8 +1866,6 @@
             // 50021 wifi_state_changed (custom|1|5)
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
-            WifiApConfigStore.initialize(mContext);
-
             if (WifiNative.isDriverLoaded()) {
                 transitionTo(mDriverLoadedState);
             }
@@ -3243,21 +3251,19 @@
             if (DBG) log(getName() + "\n");
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
-            final Message message = Message.obtain(getCurrentMessage());
-            final WifiConfiguration config = (WifiConfiguration) message.obj;
+            final Message message = getCurrentMessage();
+            if (message.what == CMD_START_AP) {
+                final WifiConfiguration config = (WifiConfiguration) message.obj;
 
-            // start hostapd on a seperate thread
-            new Thread(new Runnable() {
-                public void run() {
-                    if (startSoftApWithConfig(config)) {
-                        if (DBG) log("Soft AP start successful");
-                        sendMessage(CMD_START_AP_SUCCESS);
-                    } else {
-                        loge("Soft AP start failed");
-                        sendMessage(CMD_START_AP_FAILURE);
-                    }
+                if (config == null) {
+                    mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
+                } else {
+                    mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
+                    startSoftApWithConfig(config);
                 }
-            }).start();
+            } else {
+                throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
+            }
         }
         @Override
         public boolean processMessage(Message message) {
@@ -3282,6 +3288,15 @@
                 case WifiP2pService.P2P_ENABLE_PENDING:
                     deferMessage(message);
                     break;
+                case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
+                    WifiConfiguration config = (WifiConfiguration) message.obj;
+                    if (config != null) {
+                        startSoftApWithConfig(config);
+                    } else {
+                        loge("Softap config is null!");
+                        sendMessage(CMD_START_AP_FAILURE);
+                    }
+                    break;
                 case CMD_START_AP_SUCCESS:
                     setWifiApState(WIFI_AP_STATE_ENABLED);
                     transitionTo(mSoftApStartedState);