Merge "Bug 5575396: close spell session on language change" into ics-mr1
diff --git a/api/current.txt b/api/current.txt
index 808cb6f..d83659f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3235,6 +3235,7 @@
     method public final android.app.Fragment getTargetFragment();
     method public final int getTargetRequestCode();
     method public final java.lang.CharSequence getText(int);
+    method public boolean getUserVisibleHint();
     method public android.view.View getView();
     method public final int hashCode();
     method public static android.app.Fragment instantiate(android.content.Context, java.lang.String);
@@ -3245,7 +3246,6 @@
     method public final boolean isInLayout();
     method public final boolean isRemoving();
     method public final boolean isResumed();
-    method public boolean isStartDeferred();
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
@@ -3281,8 +3281,8 @@
     method public void setInitialSavedState(android.app.Fragment.SavedState);
     method public void setMenuVisibility(boolean);
     method public void setRetainInstance(boolean);
-    method public void setStartDeferred(boolean);
     method public void setTargetFragment(android.app.Fragment, int);
+    method public void setUserVisibleHint(boolean);
     method public void startActivity(android.content.Intent);
     method public void startActivityForResult(android.content.Intent, int);
     method public void unregisterForContextMenu(android.view.View);
@@ -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";
@@ -18813,6 +18878,7 @@
     method public boolean areDefaultsEnforced();
     method public java.lang.String getDefaultEngine();
     method public java.util.List<android.speech.tts.TextToSpeech.EngineInfo> getEngines();
+    method public java.util.Set<java.lang.String> getFeatures(java.util.Locale);
     method public java.util.Locale getLanguage();
     method public int isLanguageAvailable(java.util.Locale);
     method public boolean isSpeaking();
@@ -18858,6 +18924,8 @@
     field public static final java.lang.String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
     field public static final java.lang.String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
     field public static final java.lang.String INTENT_ACTION_TTS_SERVICE = "android.intent.action.TTS_SERVICE";
+    field public static final java.lang.String KEY_FEATURE_EMBEDDED_SYNTHESIS = "embeddedTts";
+    field public static final java.lang.String KEY_FEATURE_NETWORK_SYNTHESIS = "networkTts";
     field public static final java.lang.String KEY_PARAM_PAN = "pan";
     field public static final java.lang.String KEY_PARAM_STREAM = "streamType";
     field public static final java.lang.String KEY_PARAM_UTTERANCE_ID = "utteranceId";
@@ -18883,6 +18951,7 @@
   public abstract class TextToSpeechService extends android.app.Service {
     ctor public TextToSpeechService();
     method public android.os.IBinder onBind(android.content.Intent);
+    method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String);
     method protected abstract java.lang.String[] onGetLanguage();
     method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
     method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
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/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 30aed33..ca66a4e 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -209,6 +209,8 @@
 
     run_command("LIST OF OPEN FILES", 10, "su", "root", "lsof", NULL);
 
+    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
+
 #ifdef BOARD_HAS_DUMPSTATE
     printf("========================================================\n");
     printf("== Board\n");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 597ab1f..6d66b1b 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -45,6 +45,9 @@
 /* Displays a blocked processes in-kernel wait channel */
 void show_wchan(int pid, const char *name);
 
+/* Runs "showmap" for a process */
+void do_showmap(int pid, const char *name);
+
 /* Play a sound via Stagefright */
 void play_sound(const char* path);
 
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index b2f9e80..14984ec 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -96,6 +96,15 @@
     return;
 }
 
+void do_showmap(int pid, const char *name) {
+    char title[255];
+    char arg[255];
+
+    sprintf(title, "SHOW MAP %d (%s)", pid, name);
+    sprintf(arg, "%d", pid);
+    run_command(title, 10, "su", "root", "showmap", arg, NULL);
+}
+
 /* prints the contents of a file */
 int dump_file(const char *title, const char* path) {
     char buffer[32768];
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/Fragment.java b/core/java/android/app/Fragment.java
index 9b01b7f..473a2d1 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -458,6 +458,9 @@
     // have been started and their loaders are finished.
     boolean mDeferStart;
 
+    // Hint provided by the app that this fragment is currently visible to the user.
+    boolean mUserVisibleHint = true;
+
     LoaderManagerImpl mLoaderManager;
     boolean mLoadersStarted;
     boolean mCheckedForLoaderManager;
@@ -915,31 +918,32 @@
     }
 
     /**
-     * Set whether this fragment should enter the started state as normal or if
-     * start should be deferred until a system-determined convenient time, such
-     * as after any loaders have completed their work.
+     * Set a hint to the system about whether this fragment's UI is currently visible
+     * to the user. This hint defaults to true and is persistent across fragment instance
+     * state save and restore.
      *
-     * <p>This option is not sticky across fragment starts; after a deferred start
-     * completes this option will be set to false.</p>
+     * <p>An app may set this to false to indicate that the fragment's UI is
+     * scrolled out of visibility or is otherwise not directly visible to the user.
+     * This may be used by the system to prioritize operations such as fragment lifecycle updates
+     * or loader ordering behavior.</p>
      *
-     * @param deferResume true if this fragment can defer its resume until after others
+     * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default),
+     *                        false if it is not.
      */
-    public void setStartDeferred(boolean deferResume) {
-        if (mDeferStart && !deferResume) {
+    public void setUserVisibleHint(boolean isVisibleToUser) {
+        if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) {
             mFragmentManager.performPendingDeferredStart(this);
         }
-        mDeferStart = deferResume;
+        mUserVisibleHint = isVisibleToUser;
+        mDeferStart = !isVisibleToUser;
     }
 
     /**
-     * Returns true if this fragment's move to the started state has been deferred.
-     * If this returns true it will be started once other fragments' loaders
-     * have finished running.
-     *
-     * @return true if this fragment's start has been deferred.
+     * @return The current value of the user-visible hint on this fragment.
+     * @see #setUserVisibleHint(boolean)
      */
-    public boolean isStartDeferred() {
-        return mDeferStart;
+    public boolean getUserVisibleHint() {
+        return mUserVisibleHint;
     }
 
     /**
@@ -1477,7 +1481,8 @@
                 writer.print(" mMenuVisible="); writer.print(mMenuVisible);
                 writer.print(" mHasMenu="); writer.println(mHasMenu);
         writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance);
-                writer.print(" mRetaining="); writer.println(mRetaining);
+                writer.print(" mRetaining="); writer.print(mRetaining);
+                writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint);
         if (mFragmentManager != null) {
             writer.print(prefix); writer.print("mFragmentManager=");
                     writer.println(mFragmentManager);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index c4ba778..a8c9cba 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -382,6 +382,7 @@
     static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
     static final String TARGET_STATE_TAG = "android:target_state";
     static final String VIEW_STATE_TAG = "android:view_state";
+    static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
 
     ArrayList<Runnable> mPendingActions;
     Runnable[] mTmpActions;
@@ -406,6 +407,7 @@
     boolean mStateSaved;
     boolean mDestroyed;
     String mNoTransactionsBecause;
+    boolean mHavePendingDeferredStart;
     
     // Temporary vars for state save and restore.
     Bundle mStateBundle = null;
@@ -711,6 +713,11 @@
     
     public void performPendingDeferredStart(Fragment f) {
         if (f.mDeferStart) {
+            if (mExecutingActions) {
+                // Wait until we're done executing our pending transactions
+                mHavePendingDeferredStart = true;
+                return;
+            }
             f.mDeferStart = false;
             moveToState(f, mCurState, 0, 0);
         }
@@ -757,6 +764,14 @@
                             f.mTargetRequestCode = f.mSavedFragmentState.getInt(
                                     FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
                         }
+                        f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
+                                FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
+                        if (!f.mUserVisibleHint) {
+                            f.mDeferStart = true;
+                            if (newState > Fragment.STOPPED) {
+                                newState = Fragment.STOPPED;
+                            }
+                        }
                     }
                     f.mActivity = mActivity;
                     f.mFragmentManager = mActivity.mFragments;
@@ -1343,7 +1358,7 @@
             
             synchronized (this) {
                 if (mPendingActions == null || mPendingActions.size() == 0) {
-                    return didSomething;
+                    break;
                 }
                 
                 numActions = mPendingActions.size();
@@ -1363,8 +1378,23 @@
             mExecutingActions = false;
             didSomething = true;
         }
+
+        if (mHavePendingDeferredStart) {
+            boolean loadersRunning = false;
+            for (int i=0; i<mActive.size(); i++) {
+                Fragment f = mActive.get(i);
+                if (f != null && f.mLoaderManager != null) {
+                    loadersRunning |= f.mLoaderManager.hasRunningLoaders();
+                }
+            }
+            if (!loadersRunning) {
+                mHavePendingDeferredStart = false;
+                startPendingDeferredFragments();
+            }
+        }
+        return didSomething;
     }
-    
+
     void reportBackStackChanged() {
         if (mBackStackChangeListeners != null) {
             for (int i=0; i<mBackStackChangeListeners.size(); i++) {
@@ -1500,6 +1530,10 @@
             result.putSparseParcelableArray(
                     FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
         }
+        if (!f.mUserVisibleHint) {
+            // Only add this if it's not the default value
+            result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
+        }
 
         return result;
     }
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/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3eb7647..8541748d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -153,10 +153,14 @@
     public static final int GET_PERMISSIONS               = 0x00001000;
 
     /**
-     * Flag parameter to retrieve all applications(even uninstalled ones) with data directories.
-     * This state could have resulted if applications have been deleted with flag
-     * DONT_DELETE_DATA
-     * with a possibility of being replaced or reinstalled in future
+     * Flag parameter to retrieve some information about all applications (even
+     * uninstalled ones) which have data directories. This state could have
+     * resulted if applications have been deleted with flag
+     * {@code DONT_DELETE_DATA} with a possibility of being replaced or
+     * reinstalled in future.
+     * <p>
+     * Note: this flag may cause less information about currently installed
+     * applications to be returned.
      */
     public static final int GET_UNINSTALLED_PACKAGES = 0x00002000;
 
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/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index be87946..6ecc640 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -105,6 +105,18 @@
     void removeRoute(String iface, in RouteInfo route);
 
     /**
+     * Add the specified route to a secondary interface
+     * This will go into a special route table to be accessed
+     * via ip rules
+     */
+    void addSecondaryRoute(String iface, in RouteInfo route);
+
+    /**
+     * Remove the specified secondary route.
+     */
+    void removeSecondaryRoute(String iface, in RouteInfo route);
+
+    /**
      * Shuts down the service
      */
     void shutdown();
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index cc2fa85..99f58a0 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -116,6 +116,14 @@
     private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
 
     /**
+     * Boolean system property to disable strict mode checks outright.
+     * Set this to 'true' to force disable; 'false' has no effect on other
+     * enable/disable policy.
+     * @hide
+     */
+    public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable";
+
+    /**
      * The boolean system property to control screen flashes on violations.
      *
      * @hide
@@ -891,16 +899,24 @@
      * @hide
      */
     public static boolean conditionallyEnableDebugLogging() {
-        boolean doFlashes = !amTheSystemServerProcess() &&
-                SystemProperties.getBoolean(VISUAL_PROPERTY, IS_ENG_BUILD);
+        boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false)
+                && !amTheSystemServerProcess();
+        final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false);
 
         // For debug builds, log event loop stalls to dropbox for analysis.
         // Similar logic also appears in ActivityThread.java for system apps.
-        if (IS_USER_BUILD && !doFlashes) {
+        if (!doFlashes && (IS_USER_BUILD || suppress)) {
             setCloseGuardEnabled(false);
             return false;
         }
 
+        // Eng builds have flashes on all the time.  The suppression property
+        // overrides this, so we force the behavior only after the short-circuit
+        // check above.
+        if (IS_ENG_BUILD) {
+            doFlashes = true;
+        }
+
         // Thread policy controls BlockGuard.
         int threadPolicyMask = StrictMode.DETECT_DISK_WRITE |
                 StrictMode.DETECT_DISK_READ |
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 4bc0892..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 {
         /**
@@ -4666,6 +4660,13 @@
          * @hide
          */
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_lookup";
+
+       /**
+        * Boolean parameter that is used to look up a SIP address.
+        *
+        * @hide
+        */
+        public static final String QUERY_PARAMETER_SIP_ADDRESS = "sip";
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5754e60..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.
@@ -3620,6 +3629,13 @@
                 "pdp_watchdog_max_pdp_reset_fail_count";
 
         /**
+         * The number of milliseconds to delay when checking for data stalls
+         * @hide
+         */
+        public static final String DATA_STALL_ALARM_DELAY_IN_MS =
+                "data_stall_alarm_delay_in_ms";
+
+        /**
          * The interval in milliseconds at which to check gprs registration
          * after the first registration mismatch of gprs and voice service,
          * to detect possible data network registration problems.
@@ -4061,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
@@ -4097,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/speech/tts/ITextToSpeechService.aidl b/core/java/android/speech/tts/ITextToSpeechService.aidl
index ff3fa11..1a8c1fb 100644
--- a/core/java/android/speech/tts/ITextToSpeechService.aidl
+++ b/core/java/android/speech/tts/ITextToSpeechService.aidl
@@ -114,6 +114,21 @@
     int isLanguageAvailable(in String lang, in String country, in String variant);
 
     /**
+     * Returns a list of features available for a given language. Elements of the returned
+     * string array can be passed in as keys to {@link TextToSpeech#speak} and
+     * {@link TextToSpeech#synthesizeToFile} to select a given feature or features to be
+     * used during synthesis.
+     *
+     * @param lang ISO-3 language code.
+     * @param country ISO-3 country code. May be empty or null.
+     * @param variant Language variant. May be empty or null.
+     * @return An array of strings containing the set of features supported for
+     *         the supplied locale. The array of strings must not contain 
+     *         duplicates.
+     */
+    String[] getFeaturesForLanguage(in String lang, in String country, in String variant);
+
+    /**
      * Notifies the engine that it should load a speech synthesis language.
      *
      * @param lang ISO-3 language code.
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 98ab310..fdc2570 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -31,10 +31,13 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 /**
  *
@@ -147,7 +150,25 @@
     }
 
     /**
-     * Constants and parameter names for controlling text-to-speech.
+     * Constants and parameter names for controlling text-to-speech. These include:
+     *
+     * <ul>
+     *     <li>
+     *         Intents to ask engine to install data or check its data and
+     *         extras for a TTS engine's check data activity.
+     *     </li>
+     *     <li>
+     *         Keys for the parameters passed with speak commands, e.g.
+     *         {@link Engine#KEY_PARAM_UTTERANCE_ID}, {@link Engine#KEY_PARAM_STREAM}.
+     *     </li>
+     *     <li>
+     *         A list of feature strings that engines might support, e.g
+     *         {@link Engine#KEY_FEATURE_NETWORK_SYNTHESIS}). These values may be passed in to
+     *         {@link TextToSpeech#speak} and {@link TextToSpeech#synthesizeToFile} to modify
+     *         engine behaviour. The engine can be queried for the set of features it supports
+     *         through {@link TextToSpeech#getFeatures(java.util.Locale)}.
+     *     </li>
+     * </ul>
      */
     public class Engine {
 
@@ -435,6 +456,25 @@
          */
         public static final String KEY_PARAM_PAN = "pan";
 
+        /**
+         * Feature key for network synthesis. See {@link TextToSpeech#getFeatures(Locale)}
+         * for a description of how feature keys work. If set (and supported by the engine
+         * as per {@link TextToSpeech#getFeatures(Locale)}, the engine must
+         * use network based synthesis.
+         *
+         * @see TextToSpeech#speak(String, int, java.util.HashMap)
+         * @see TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)
+         * @see TextToSpeech#getFeatures(java.util.Locale)
+         */
+        public static final String KEY_FEATURE_NETWORK_SYNTHESIS = "networkTts";
+
+        /**
+         * Feature key for embedded synthesis. See {@link TextToSpeech#getFeatures(Locale)}
+         * for a description of how feature keys work. If set and supported by the engine
+         * as per {@link TextToSpeech#getFeatures(Locale)}, the engine must synthesize
+         * text on-device (without making network requests).
+         */
+        public static final String KEY_FEATURE_EMBEDDED_SYNTHESIS = "embeddedTts";
     }
 
     private final Context mContext;
@@ -812,6 +852,36 @@
     }
 
     /**
+     * Queries the engine for the set of features it supports for a given locale.
+     * Features can either be framework defined, e.g.
+     * {@link TextToSpeech.Engine#KEY_FEATURE_NETWORK_SYNTHESIS} or engine specific.
+     * Engine specific keys must be prefixed by the name of the engine they
+     * are intended for. These keys can be used as parameters to
+     * {@link TextToSpeech#speak(String, int, java.util.HashMap)} and
+     * {@link TextToSpeech#synthesizeToFile(String, java.util.HashMap, String)}.
+     *
+     * Features are boolean flags, and their values in the synthesis parameters
+     * must be behave as per {@link Boolean#parseBoolean(String)}.
+     *
+     * @param locale The locale to query features for.
+     */
+    public Set<String> getFeatures(final Locale locale) {
+        return runAction(new Action<Set<String>>() {
+            @Override
+            public Set<String> run(ITextToSpeechService service) throws RemoteException {
+                String[] features = service.getFeaturesForLanguage(
+                        locale.getISO3Language(), locale.getISO3Country(), locale.getVariant());
+                if (features != null) {
+                    final Set<String> featureSet = new HashSet<String>();
+                    Collections.addAll(featureSet, features);
+                    return featureSet;
+                }
+                return null;
+            }
+        }, null, "getFeatures");
+    }
+
+    /**
      * Checks whether the TTS engine is busy speaking. Note that a speech item is
      * considered complete once it's audio data has been sent to the audio mixer, or
      * written to a file. There might be a finite lag between this point, and when
@@ -1017,6 +1087,10 @@
             copyFloatParam(bundle, params, Engine.KEY_PARAM_VOLUME);
             copyFloatParam(bundle, params, Engine.KEY_PARAM_PAN);
 
+            // Copy feature strings defined by the framework.
+            copyStringParam(bundle, params, Engine.KEY_FEATURE_NETWORK_SYNTHESIS);
+            copyStringParam(bundle, params, Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
+
             // Copy over all parameters that start with the name of the
             // engine that we are currently connected to. The engine is
             // free to interpret them as it chooses.
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 48739ba..83b6d4c 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -36,6 +36,7 @@
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Locale;
+import java.util.Set;
 
 
 /**
@@ -67,7 +68,6 @@
  * any. Any pending data from the current synthesis will be discarded.
  *
  */
-// TODO: Add a link to the sample TTS engine once it's done.
 public abstract class TextToSpeechService extends Service {
 
     private static final boolean DBG = false;
@@ -196,6 +196,18 @@
     protected abstract void onSynthesizeText(SynthesisRequest request,
             SynthesisCallback callback);
 
+    /**
+     * Queries the service for a set of features supported for a given language.
+     *
+     * @param lang ISO-3 language code.
+     * @param country ISO-3 country code. May be empty or null.
+     * @param variant Language variant. May be empty or null.
+     * @return A list of features supported for the given language.
+     */
+    protected Set<String> onGetFeaturesForLanguage(String lang, String country, String variant) {
+        return null;
+    }
+
     private int getDefaultSpeechRate() {
         return getSecureSettingInt(Settings.Secure.TTS_DEFAULT_RATE, Engine.DEFAULT_RATE);
     }
@@ -778,6 +790,18 @@
             return onIsLanguageAvailable(lang, country, variant);
         }
 
+        public String[] getFeaturesForLanguage(String lang, String country, String variant) {
+            Set<String> features = onGetFeaturesForLanguage(lang, country, variant);
+            String[] featuresArray = null;
+            if (features != null) {
+                featuresArray = new String[features.size()];
+                features.toArray(featuresArray);
+            } else {
+                featuresArray = new String[0];
+            }
+            return featuresArray;
+        }
+
         /*
          * There is no point loading a non default language if defaults
          * are enforced.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 24423c3..f7078ec 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -218,6 +218,7 @@
     boolean mNewSurfaceNeeded;
     boolean mHasHadWindowFocus;
     boolean mLastWasImTarget;
+    InputEventMessage mPendingInputEvents = null;
 
     boolean mWindowAttributesChanged = false;
     int mWindowAttributesChangesFlag = 0;
@@ -832,10 +833,24 @@
         }
     }
 
+    private void processInputEvents(boolean outOfOrder) {
+        while (mPendingInputEvents != null) {
+            handleMessage(mPendingInputEvents.mMessage);
+            InputEventMessage tmpMessage = mPendingInputEvents;
+            mPendingInputEvents = mPendingInputEvents.mNext;
+            tmpMessage.recycle();
+            if (outOfOrder) {
+                removeMessages(PROCESS_INPUT_EVENTS);
+            }
+        }
+    }
+
     private void performTraversals() {
         // cache mView since it is used so much below...
         final View host = mView;
 
+        processInputEvents(true);
+
         if (DBG) {
             System.out.println("======================================");
             System.out.println("performTraversals");
@@ -2336,6 +2351,7 @@
     public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 1021;
     public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 1022;
     public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT = 1023;
+    public final static int PROCESS_INPUT_EVENTS = 1024;
 
     @Override
     public String getMessageName(Message message) {
@@ -2388,7 +2404,9 @@
                 return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID";
             case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT:
                 return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT";
-                                                                                                                                                                                                                                    
+            case PROCESS_INPUT_EVENTS:
+                return "PROCESS_INPUT_EVENTS";
+
         }
         return super.getMessageName(message);
     }
@@ -2447,6 +2465,9 @@
         case DISPATCH_GENERIC_MOTION:
             deliverGenericMotionEvent((MotionEvent) msg.obj, msg.arg1 != 0);
             break;
+        case PROCESS_INPUT_EVENTS:
+            processInputEvents(false);
+            break;
         case DISPATCH_APP_VISIBILITY:
             handleAppVisibility(msg.arg1 != 0);
             break;
@@ -3744,7 +3765,7 @@
         msg.obj = ri;
         sendMessage(msg);
     }
-    
+
     private long mInputEventReceiveTimeNanos;
     private long mInputEventDeliverTimeNanos;
     private long mInputEventDeliverPostImeTimeNanos;
@@ -3762,6 +3783,78 @@
         }
     };
 
+    /**
+     * Utility class used to queue up input events which are then handled during
+     * performTraversals(). Doing it this way allows us to ensure that we are up to date with
+     * all input events just prior to drawing, instead of placing those events on the regular
+     * handler queue, potentially behind a drawing event.
+     */
+    static class InputEventMessage {
+        Message mMessage;
+        InputEventMessage mNext;
+
+        private static final Object sPoolSync = new Object();
+        private static InputEventMessage sPool;
+        private static int sPoolSize = 0;
+
+        private static final int MAX_POOL_SIZE = 10;
+
+        private InputEventMessage(Message m) {
+            mMessage = m;
+            mNext = null;
+        }
+
+        /**
+         * Return a new Message instance from the global pool. Allows us to
+         * avoid allocating new objects in many cases.
+         */
+        public static InputEventMessage obtain(Message msg) {
+            synchronized (sPoolSync) {
+                if (sPool != null) {
+                    InputEventMessage m = sPool;
+                    sPool = m.mNext;
+                    m.mNext = null;
+                    sPoolSize--;
+                    m.mMessage = msg;
+                    return m;
+                }
+            }
+            return new InputEventMessage(msg);
+        }
+
+        /**
+         * Return the message to the pool.
+         */
+        public void recycle() {
+            mMessage.recycle();
+            synchronized (sPoolSync) {
+                if (sPoolSize < MAX_POOL_SIZE) {
+                    mNext = sPool;
+                    sPool = this;
+                    sPoolSize++;
+                }
+            }
+
+        }
+    }
+
+    /**
+     * Place the input event message at the end of the current pending list
+     */
+    private void enqueueInputEvent(Message msg, long when) {
+        InputEventMessage inputMessage = InputEventMessage.obtain(msg);
+        if (mPendingInputEvents == null) {
+            mPendingInputEvents = inputMessage;
+        } else {
+            InputEventMessage currMessage = mPendingInputEvents;
+            while (currMessage.mNext != null) {
+                currMessage = currMessage.mNext;
+            }
+            currMessage.mNext = inputMessage;
+        }
+        sendEmptyMessageAtTime(PROCESS_INPUT_EVENTS, when);
+    }
+
     public void dispatchKey(KeyEvent event) {
         dispatchKey(event, false);
     }
@@ -3786,7 +3879,7 @@
         if (LOCAL_LOGV) Log.v(
             TAG, "sending key " + event + " to " + mView);
 
-        sendMessageAtTime(msg, event.getEventTime());
+        enqueueInputEvent(msg, event.getEventTime());
     }
     
     private void dispatchMotion(MotionEvent event, boolean sendDone) {
@@ -3804,21 +3897,21 @@
         Message msg = obtainMessage(DISPATCH_POINTER);
         msg.obj = event;
         msg.arg1 = sendDone ? 1 : 0;
-        sendMessageAtTime(msg, event.getEventTime());
+        enqueueInputEvent(msg, event.getEventTime());
     }
 
     private void dispatchTrackball(MotionEvent event, boolean sendDone) {
         Message msg = obtainMessage(DISPATCH_TRACKBALL);
         msg.obj = event;
         msg.arg1 = sendDone ? 1 : 0;
-        sendMessageAtTime(msg, event.getEventTime());
+        enqueueInputEvent(msg, event.getEventTime());
     }
 
     private void dispatchGenericMotion(MotionEvent event, boolean sendDone) {
         Message msg = obtainMessage(DISPATCH_GENERIC_MOTION);
         msg.obj = event;
         msg.arg1 = sendDone ? 1 : 0;
-        sendMessageAtTime(msg, event.getEventTime());
+        enqueueInputEvent(msg, event.getEventTime());
     }
 
     public void dispatchAppVisibility(boolean visible) {
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 2cc928f..388920c 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -813,8 +813,6 @@
                                               boolean synchronous,
                                               String username,
                                               String password) {
-        PerfChecker checker = new PerfChecker();
-
         if (mSettings.getCacheMode() != WebSettings.LOAD_DEFAULT) {
             cacheMode = mSettings.getCacheMode();
         }
@@ -872,11 +870,6 @@
                 || headers.containsKey("If-None-Match") ? 
                         WebSettings.LOAD_NO_CACHE : cacheMode);
         // Set referrer to current URL?
-        if (!loader.executeLoad()) {
-            checker.responseAlert("startLoadingResource fail");
-        }
-        checker.responseAlert("startLoadingResource succeed");
-
         return !synchronous ? loadListener : null;
     }
 
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index 5b78586..b498435 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -87,11 +87,9 @@
      * Call native timer callbacks.
      */
     private void fireSharedTimer() { 
-        PerfChecker checker = new PerfChecker();
         // clear the flag so that sharedTimerFired() can set a new timer
         mHasInstantTimer = false;
         sharedTimerFired();
-        checker.responseAlert("sharedTimer");
     }
 
     /**
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 04af738..37e8bc0 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -1136,7 +1136,6 @@
         // Give the data to WebKit now. We don't have to synchronize on
         // mDataBuilder here because pulling each chunk removes it from the
         // internal list so it cannot be modified.
-        PerfChecker checker = new PerfChecker();
         ByteArrayBuilder.Chunk c;
         while (true) {
             c = mDataBuilder.getFirstChunk();
@@ -1152,7 +1151,6 @@
             } else {
                 c.release();
             }
-            checker.responseAlert("res nativeAddData");
         }
     }
 
@@ -1173,13 +1171,11 @@
                     WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
         }
         if (mNativeLoader != 0) {
-            PerfChecker checker = new PerfChecker();
             if (!mSetNativeResponse) {
                 setNativeResponse();
             }
 
             nativeFinished();
-            checker.responseAlert("res nativeFinished");
             clearNativeLoader();
         }
     }
diff --git a/core/java/android/webkit/PerfChecker.java b/core/java/android/webkit/PerfChecker.java
deleted file mode 100644
index 8c5f86e..0000000
--- a/core/java/android/webkit/PerfChecker.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.webkit;
-
-import android.os.SystemClock;
-import android.util.Log;
-
-class PerfChecker {
-
-    private long mTime;
-    private static final long mResponseThreshold = 2000;    // 2s
-
-    public PerfChecker() {
-        if (false) {
-            mTime = SystemClock.uptimeMillis();
-        }
-    }
-
-    /**
-     * @param what log string
-     * Logs given string if mResponseThreshold time passed between either
-     * instantiation or previous responseAlert call
-     */
-    public void responseAlert(String what) {
-        if (false) {
-            long upTime = SystemClock.uptimeMillis();
-            long time =  upTime - mTime;
-            if (time > mResponseThreshold) {
-                Log.w("webkit", what + " used " + time + " ms");
-            }
-            // Reset mTime, to permit reuse
-            mTime = upTime;
-        }
-    }
-}
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/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 58b63fe..55f345f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -683,7 +683,6 @@
     private static final int SWITCH_TO_LONGPRESS        = 4;
     private static final int RELEASE_SINGLE_TAP         = 5;
     private static final int REQUEST_FORM_DATA          = 6;
-    private static final int RESUME_WEBCORE_PRIORITY    = 7;
     private static final int DRAG_HELD_MOTIONLESS       = 8;
     private static final int AWAKEN_SCROLL_BARS         = 9;
     private static final int PREVENT_DEFAULT_TIMEOUT    = 10;
@@ -2850,46 +2849,47 @@
     // Used to avoid sending many visible rect messages.
     private Rect mLastVisibleRectSent;
     private Rect mLastGlobalRect;
+    private Rect mVisibleRect = new Rect();
+    private Rect mGlobalVisibleRect = new Rect();
+    private Point mScrollOffset = new Point();
 
     Rect sendOurVisibleRect() {
         if (mZoomManager.isPreventingWebkitUpdates()) return mLastVisibleRectSent;
-        Rect rect = new Rect();
-        calcOurContentVisibleRect(rect);
+        calcOurContentVisibleRect(mVisibleRect);
         // Rect.equals() checks for null input.
-        if (!rect.equals(mLastVisibleRectSent)) {
+        if (!mVisibleRect.equals(mLastVisibleRectSent)) {
             if (!mBlockWebkitViewMessages) {
-                Point pos = new Point(rect.left, rect.top);
+                mScrollOffset.set(mVisibleRect.left, mVisibleRect.top);
                 mWebViewCore.removeMessages(EventHub.SET_SCROLL_OFFSET);
                 mWebViewCore.sendMessage(EventHub.SET_SCROLL_OFFSET,
-                        nativeMoveGeneration(), mSendScrollEvent ? 1 : 0, pos);
+                        nativeMoveGeneration(), mSendScrollEvent ? 1 : 0, mScrollOffset);
             }
-            mLastVisibleRectSent = rect;
+            mLastVisibleRectSent = mVisibleRect;
             mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
         }
-        Rect globalRect = new Rect();
-        if (getGlobalVisibleRect(globalRect)
-                && !globalRect.equals(mLastGlobalRect)) {
+        if (getGlobalVisibleRect(mGlobalVisibleRect)
+                && !mGlobalVisibleRect.equals(mLastGlobalRect)) {
             if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "sendOurVisibleRect=(" + globalRect.left + ","
-                        + globalRect.top + ",r=" + globalRect.right + ",b="
-                        + globalRect.bottom);
+                Log.v(LOGTAG, "sendOurVisibleRect=(" + mGlobalVisibleRect.left + ","
+                        + mGlobalVisibleRect.top + ",r=" + mGlobalVisibleRect.right + ",b="
+                        + mGlobalVisibleRect.bottom);
             }
             // TODO: the global offset is only used by windowRect()
             // in ChromeClientAndroid ; other clients such as touch
             // and mouse events could return view + screen relative points.
             if (!mBlockWebkitViewMessages) {
-                mWebViewCore.sendMessage(EventHub.SET_GLOBAL_BOUNDS, globalRect);
+                mWebViewCore.sendMessage(EventHub.SET_GLOBAL_BOUNDS, mGlobalVisibleRect);
             }
-            mLastGlobalRect = globalRect;
+            mLastGlobalRect = mGlobalVisibleRect;
         }
-        return rect;
+        return mVisibleRect;
     }
 
+    private Point mGlobalVisibleOffset = new Point();
     // Sets r to be the visible rectangle of our webview in view coordinates
     private void calcOurVisibleRect(Rect r) {
-        Point p = new Point();
-        getGlobalVisibleRect(r, p);
-        r.offset(-p.x, -p.y);
+        getGlobalVisibleRect(r, mGlobalVisibleOffset);
+        r.offset(-mGlobalVisibleOffset.x, -mGlobalVisibleOffset.y);
     }
 
     // Sets r to be our visible rectangle in content coordinates
@@ -2905,21 +2905,21 @@
         r.bottom = viewToContentY(r.bottom);
     }
 
+    private Rect mContentVisibleRect = new Rect();
     // Sets r to be our visible rectangle in content coordinates. We use this
     // method on the native side to compute the position of the fixed layers.
     // Uses floating coordinates (necessary to correctly place elements when
     // the scale factor is not 1)
     private void calcOurContentVisibleRectF(RectF r) {
-        Rect ri = new Rect(0,0,0,0);
-        calcOurVisibleRect(ri);
-        r.left = viewToContentXf(ri.left);
+        calcOurVisibleRect(mContentVisibleRect);
+        r.left = viewToContentXf(mContentVisibleRect.left);
         // viewToContentY will remove the total height of the title bar.  Add
         // the visible height back in to account for the fact that if the title
         // bar is partially visible, the part of the visible rect which is
         // displaying our content is displaced by that amount.
-        r.top = viewToContentYf(ri.top + getVisibleTitleHeightImpl());
-        r.right = viewToContentXf(ri.right);
-        r.bottom = viewToContentYf(ri.bottom);
+        r.top = viewToContentYf(mContentVisibleRect.top + getVisibleTitleHeightImpl());
+        r.right = viewToContentXf(mContentVisibleRect.right);
+        r.bottom = viewToContentYf(mContentVisibleRect.bottom);
     }
 
     static class ViewSizeData {
@@ -3569,7 +3569,6 @@
                     mScrollingLayerRect.top = y;
                 }
                 abortAnimation();
-                mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
                 nativeSetIsScrolling(false);
                 if (!mBlockWebkitViewMessages) {
                     WebViewCore.resumePriority();
@@ -4119,20 +4118,6 @@
     }
 
     private void drawContent(Canvas canvas, boolean drawRings) {
-        // Update the buttons in the picture, so when we draw the picture
-        // to the screen, they are in the correct state.
-        // Tell the native side if user is a) touching the screen,
-        // b) pressing the trackball down, or c) pressing the enter key
-        // If the cursor is on a button, we need to draw it in the pressed
-        // state.
-        // If mNativeClass is 0, we should not reach here, so we do not
-        // need to check it again.
-        boolean pressed = (mTouchMode == TOUCH_SHORTPRESS_START_MODE
-                || mTouchMode == TOUCH_INIT_MODE
-                || mTouchMode == TOUCH_SHORTPRESS_MODE);
-        recordButtons(canvas,
-                hasFocus() && hasWindowFocus(), (pressed && !USE_WEBKIT_RINGS)
-                || mTrackballDown || mGotCenterDown, false);
         drawCoreAndCursorRing(canvas, mBackgroundColor,
                 mDrawCursorRing && drawRings);
     }
@@ -5193,9 +5178,6 @@
                 mGotCenterDown = true;
                 mPrivateHandler.sendMessageDelayed(mPrivateHandler
                         .obtainMessage(LONG_PRESS_CENTER), LONG_PRESS_TIMEOUT);
-                // Already checked mNativeClass, so we do not need to check it
-                // again.
-                recordButtons(null, hasFocus() && hasWindowFocus(), true, true);
                 if (!wantsKeyEvents) return true;
             }
             // Bubble up the key event as WebView doesn't handle it
@@ -5631,9 +5613,6 @@
                 // drawing the cursor ring
                 mDrawCursorRing = true;
                 setFocusControllerActive(true);
-                if (mNativeClass != 0) {
-                    recordButtons(null, true, false, true);
-                }
             } else {
                 if (!inEditingMode()) {
                     // If our window gained focus, but we do not have it, do not
@@ -5659,9 +5638,6 @@
             mKeysPressed.clear();
             mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
             mTouchMode = TOUCH_DONE_MODE;
-            if (mNativeClass != 0) {
-                recordButtons(null, false, false, true);
-            }
             setFocusControllerActive(false);
         }
         invalidate();
@@ -5717,9 +5693,6 @@
             // the cursor ring
             if (hasWindowFocus()) {
                 mDrawCursorRing = true;
-                if (mNativeClass != 0) {
-                    recordButtons(null, true, false, true);
-                }
                 setFocusControllerActive(true);
             //} else {
                 // The WebView has gained focus while we do not have
@@ -5731,9 +5704,6 @@
             // true if we are in editing mode), stop drawing the cursor ring.
             if (!inEditingMode()) {
                 mDrawCursorRing = false;
-                if (mNativeClass != 0) {
-                    recordButtons(null, false, false, true);
-                }
                 setFocusControllerActive(false);
             }
             mKeysPressed.clear();
@@ -6021,7 +5991,6 @@
                     mScroller.abortAnimation();
                     mTouchMode = TOUCH_DRAG_START_MODE;
                     mConfirmMove = true;
-                    mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
                     nativeSetIsScrolling(false);
                 } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
                     mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
@@ -6847,7 +6816,6 @@
             if (mNativeClass == 0) {
                 return false;
             }
-            recordButtons(null, hasFocus() && hasWindowFocus(), true, true);
             if (time - mLastCursorTime <= TRACKBALL_TIMEOUT
                     && !mLastCursorBounds.equals(nativeGetCursorRingBounds())) {
                 nativeSelectBestAt(mLastCursorBounds);
@@ -7359,7 +7327,6 @@
         mLastTouchTime = eventTime;
         if (!mScroller.isFinished()) {
             abortAnimation();
-            mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
         }
         mSnapScrollMode = SNAP_NONE;
         mVelocityTracker = VelocityTracker.obtain();
@@ -8491,10 +8458,6 @@
                         mWebTextView.setAdapterCustom(adapter);
                     }
                     break;
-                case RESUME_WEBCORE_PRIORITY:
-                    WebViewCore.resumePriority();
-                    WebViewCore.resumeUpdatePicture(mWebViewCore);
-                    break;
 
                 case LONG_PRESS_CENTER:
                     // as this is shared by keydown and trackballdown, reset all
@@ -9442,24 +9405,6 @@
         return nativeTileProfilingGetFloat(frame, tile, key);
     }
 
-    /**
-     * Helper method to deal with differences between hardware and software rendering
-     */
-    private void recordButtons(Canvas canvas, boolean focus, boolean pressed,
-            boolean inval) {
-        boolean isHardwareAccel = canvas != null
-                ? canvas.isHardwareAccelerated()
-                : isHardwareAccelerated();
-        if (isHardwareAccel) {
-            // We never want to change button state if we are hardware accelerated,
-            // but we DO want to invalidate as necessary so that the GL ring
-            // can be drawn
-            nativeRecordButtons(mNativeClass, false, false, inval);
-        } else {
-            nativeRecordButtons(mNativeClass, focus, pressed, inval);
-        }
-    }
-
     private native int nativeCacheHitFramePointer();
     private native boolean  nativeCacheHitIsPlugin();
     private native Rect nativeCacheHitNodeBounds();
@@ -9556,8 +9501,6 @@
     private native boolean  nativePointInNavCache(int x, int y, int slop);
     // Like many other of our native methods, you must make sure that
     // mNativeClass is not null before calling this method.
-    private native void     nativeRecordButtons(int nativeInstance,
-            boolean focused, boolean pressed, boolean invalidate);
     private native void     nativeResetSelection();
     private native Point    nativeSelectableText();
     private native void     nativeSelectAll();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 22e86c7..754d6e9 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2416,7 +2416,11 @@
         if (mIsRestored) {
             mInitialViewState.mIsRestored = true;
             mInitialViewState.mViewScale = mRestoredScale;
-            mInitialViewState.mTextWrapScale = mRestoredTextWrapScale;
+            if (mRestoredTextWrapScale > 0) {
+                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale;
+            } else {
+                mInitialViewState.mTextWrapScale = mInitialViewState.mViewScale;
+            }
         } else {
             if (mViewportInitialScale > 0) {
                 mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
@@ -2535,9 +2539,11 @@
     // called by JNI
     private void restoreScale(float scale, float textWrapScale) {
         if (mBrowserFrame.firstLayoutDone() == false) {
-            mIsRestored = true;
+            mIsRestored = scale > 0;
             mRestoredScale = scale;
-            mRestoredTextWrapScale = textWrapScale;
+            if (mSettings.getUseWideViewPort()) {
+                mRestoredTextWrapScale = textWrapScale;
+            }
         }
     }
 
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index e829571..f599dba 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -1114,7 +1114,7 @@
             float scale;
             if (mInitialScale > 0) {
                 scale = mInitialScale;
-            } else if (viewState.mIsRestored) {
+            } else if (viewState.mIsRestored || viewState.mViewScale > 0) {
                 scale = (viewState.mViewScale > 0)
                     ? viewState.mViewScale : overviewScale;
                 mTextWrapScale = (viewState.mTextWrapScale > 0)
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/SearchView.java b/core/java/android/widget/SearchView.java
index 399d217..f524ef0 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -151,6 +151,14 @@
         }
     };
 
+    private Runnable mReleaseCursorRunnable = new Runnable() {
+        public void run() {
+            if (mSuggestionsAdapter != null && mSuggestionsAdapter instanceof SuggestionsAdapter) {
+                mSuggestionsAdapter.changeCursor(null);
+            }
+        }
+    };
+
     // For voice searching
     private final Intent mVoiceWebSearchIntent;
     private final Intent mVoiceAppSearchIntent;
@@ -720,7 +728,8 @@
 
     private void updateSubmitButton(boolean hasText) {
         int visibility = GONE;
-        if (isSubmitAreaEnabled() && hasFocus() && (hasText || !mVoiceButtonEnabled)) {
+        if (mSubmitButtonEnabled && isSubmitAreaEnabled() && hasFocus()
+                && (hasText || !mVoiceButtonEnabled)) {
             visibility = VISIBLE;
         }
         mSubmitButton.setVisibility(visibility);
@@ -759,6 +768,7 @@
     @Override
     protected void onDetachedFromWindow() {
         removeCallbacks(mUpdateDrawableStateRunnable);
+        post(mReleaseCursorRunnable);
         super.onDetachedFromWindow();
     }
 
@@ -1028,7 +1038,9 @@
             }
         }
         mQueryTextView.setInputType(inputType);
-
+        if (mSuggestionsAdapter != null) {
+            mSuggestionsAdapter.changeCursor(null);
+        }
         // attach the suggestions adapter, if suggestions are available
         // The existence of a suggestions authority is the proxy for "suggestions available here"
         if (mSearchable.getSuggestAuthority() != null) {
@@ -1071,9 +1083,7 @@
         CharSequence text = mQueryTextView.getText();
         mUserQuery = text;
         boolean hasText = !TextUtils.isEmpty(text);
-        if (isSubmitButtonEnabled()) {
-            updateSubmitButton(hasText);
-        }
+        updateSubmitButton(hasText);
         updateVoiceButton(!hasText);
         updateCloseButton();
         updateSubmitArea();
@@ -1177,7 +1187,6 @@
     public void onActionViewCollapsed() {
         clearFocus();
         updateViewsVisibility(true);
-        mQueryTextView.setText("");
         mQueryTextView.setImeOptions(mCollapsedImeOptions);
         mExpandedInActionView = false;
     }
@@ -1192,6 +1201,7 @@
         mExpandedInActionView = true;
         mCollapsedImeOptions = mQueryTextView.getImeOptions();
         mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
+        mQueryTextView.setText("");
         setIconified(false);
     }
 
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index e392fd2..87c3e9b 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -86,9 +86,14 @@
 
         final TextServicesManager textServicesManager = (TextServicesManager)
                 mTextView.getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
-        mSpellCheckerSession = textServicesManager.newSpellCheckerSession(
-                null /* Bundle not currently used by the textServicesManager */,
-                locale, this, false /* means any available languages from current spell checker */);
+        if (!textServicesManager.isSpellCheckerEnabled()) {
+            mSpellCheckerSession = null;
+        } else {
+            mSpellCheckerSession = textServicesManager.newSpellCheckerSession(
+                    null /* Bundle not currently used by the textServicesManager */,
+                    locale, this,
+                    false /* means any available languages from current spell checker */);
+        }
         mCurrentLocale = locale;
 
         // Restore SpellCheckSpans in pool
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/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index 9e32c9a..c44d431 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -29,9 +29,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.database.Cursor;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.text.Spannable;
@@ -39,7 +37,6 @@
 import android.text.TextUtils;
 import android.text.style.TextAppearanceSpan;
 import android.util.Log;
-import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
@@ -113,7 +110,6 @@
 
         mOutsideDrawablesCache = outsideDrawablesCache;
         
-
         // mStartSpinnerRunnable = new Runnable() {
         // public void run() {
         // // mSearchView.setWorking(true); // TODO:
@@ -185,6 +181,10 @@
          * the results.
          */
         Cursor cursor = null;
+        if (mSearchView.getVisibility() != View.VISIBLE
+                || mSearchView.getWindowVisibility() != View.VISIBLE) {
+            return null;
+        }
         //mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO:
         try {
             cursor = mSearchManager.getSuggestions(mSearchable, query, QUERY_LIMIT);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a8680d4..5833afd 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9059,51 +9059,6 @@
         sendAccessibilityEventUnchecked(event);
     }
 
-    @Override
-    protected void onCreateContextMenu(ContextMenu menu) {
-        super.onCreateContextMenu(menu);
-        boolean added = false;
-        mContextMenuTriggeredByKey = mDPadCenterIsDown || mEnterKeyIsDown;
-        // Problem with context menu on long press: the menu appears while the key in down and when
-        // the key is released, the view does not receive the key_up event.
-        // We need two layers of flags: mDPadCenterIsDown and mEnterKeyIsDown are set in key down/up
-        // events. We cannot simply clear these flags in onTextContextMenuItem since
-        // it may not be called (if the user/ discards the context menu with the back key).
-        // We clear these flags here and mContextMenuTriggeredByKey saves that state so that it is
-        // available in onTextContextMenuItem.
-        mDPadCenterIsDown = mEnterKeyIsDown = false;
-
-        MenuHandler handler = new MenuHandler();
-
-        if (mText instanceof Spanned && hasSelectionController()) {
-            long lastTouchOffset = getLastTouchOffsets();
-            final int selStart = extractRangeStartFromLong(lastTouchOffset);
-            final int selEnd = extractRangeEndFromLong(lastTouchOffset);
-
-            URLSpan[] urls = ((Spanned) mText).getSpans(selStart, selEnd, URLSpan.class);
-            if (urls.length > 0) {
-                menu.add(0, ID_COPY_URL, 0, com.android.internal.R.string.copyUrl).
-                        setOnMenuItemClickListener(handler);
-
-                added = true;
-            }
-        }
-        
-        // The context menu is not empty, which will prevent the selection mode from starting.
-        // Add a entry to start it in the context menu.
-        // TODO Does not handle the case where a subclass does not call super.thisMethod or
-        // populates the menu AFTER this call.
-        if (menu.size() > 0) {
-            menu.add(0, ID_SELECTION_MODE, 0, com.android.internal.R.string.selectTextMode).
-                    setOnMenuItemClickListener(handler);
-            added = true;
-        }
-
-        if (added) {
-            menu.setHeaderTitle(com.android.internal.R.string.editTextMenuTitle);
-        }
-    }
-
     /**
      * Returns whether this text view is a current input method target.  The
      * default implementation just checks with {@link InputMethodManager}.
@@ -9118,9 +9073,6 @@
     private static final int ID_CUT = android.R.id.cut;
     private static final int ID_COPY = android.R.id.copy;
     private static final int ID_PASTE = android.R.id.paste;
-    // Context menu entries
-    private static final int ID_COPY_URL = android.R.id.copyUrl;
-    private static final int ID_SELECTION_MODE = android.R.id.selectTextMode;
 
     private class MenuHandler implements MenuItem.OnMenuItemClickListener {
         public boolean onMenuItemClick(MenuItem item) {
@@ -9130,9 +9082,8 @@
 
     /**
      * Called when a context menu option for the text view is selected.  Currently
-     * this will be {@link android.R.id#copyUrl}, {@link android.R.id#selectTextMode},
-     * {@link android.R.id#selectAll}, {@link android.R.id#paste}, {@link android.R.id#cut}
-     * or {@link android.R.id#copy}.
+     * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut},
+     * {@link android.R.id#copy} or {@link android.R.id#paste}.
      *
      * @return true if the context menu item action was performed.
      */
@@ -9149,34 +9100,6 @@
         }
 
         switch (id) {
-            case ID_COPY_URL:
-                URLSpan[] urls = ((Spanned) mText).getSpans(min, max, URLSpan.class);
-                if (urls.length >= 1) {
-                    ClipData clip = null;
-                    for (int i=0; i<urls.length; i++) {
-                        Uri uri = Uri.parse(urls[0].getURL());
-                        if (clip == null) {
-                            clip = ClipData.newRawUri(null, uri);
-                        } else {
-                            clip.addItem(new ClipData.Item(uri));
-                        }
-                    }
-                    if (clip != null) {
-                        setPrimaryClip(clip);
-                    }
-                }
-                stopSelectionActionMode();
-                return true;
-
-            case ID_SELECTION_MODE:
-                if (mSelectionActionMode != null) {
-                    // Selection mode is already started, simply change selected part.
-                    selectCurrentWord();
-                } else {
-                    startSelectionActionMode();
-                }
-                return true;
-
             case ID_SELECT_ALL:
                 // This does not enter text selection mode. Text is highlighted, so that it can be
                 // bulk edited, like selectAllOnFocus does. Returns true even if text is empty.
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..0ed0523 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"
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index f57126b..13ab8f7 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index f57126b..13ab8f7 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index c5adc38..1d76bb5 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index 05cb4e4..8ebd761 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index 05cb4e4..8ebd761 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index efcfa26..b405d81 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index 3b9d734..fee599a 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index 3b9d734..fee599a 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index 490b6f5..dddfc26 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index b2851834..ab40fa7 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
index b2851834..8077921 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index 57f2026..0d8f8ba 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
index 13d154f..baf7018 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
index 13d154f..baf7018 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 15b9fb9..7a24c9b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 4d83d65..7a24c9b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
index e06aef0..93c6d1b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
index d81d346..93c6d1b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
index 9f027b7..120f963 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
index a7582d6..120f963 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
index 21be9f4..6b106fb 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
index 791b318..6b106fb 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
index 8cf35b2..a1b7003 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
index e475b49..a1b7003 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index 7996db4..7176a6b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index 7996db4..7176a6b 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
index 906a229..7fba6a5 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
index 906a229..7fba6a5 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
index 56bd325..8bbfe9f 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
index 56bd325..8bbfe9f 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
index 61b2efc..28f0ee6 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
index 61b2efc..28f0ee6 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
index d2e4ca8..c4c41a3 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
index d2e4ca8..c4c41a3 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_next.png b/core/res/res/drawable-hdpi/ic_media_next.png
index f5ba824..6e27b81 100644
--- a/core/res/res/drawable-hdpi/ic_media_next.png
+++ b/core/res/res/drawable-hdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_pause.png b/core/res/res/drawable-hdpi/ic_media_pause.png
index 671148e..1d465a4 100644
--- a/core/res/res/drawable-hdpi/ic_media_pause.png
+++ b/core/res/res/drawable-hdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_play.png b/core/res/res/drawable-hdpi/ic_media_play.png
index c2e366a..2746d17 100644
--- a/core/res/res/drawable-hdpi/ic_media_play.png
+++ b/core/res/res/drawable-hdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_previous.png b/core/res/res/drawable-hdpi/ic_media_previous.png
index 40ecb00..85b3766 100644
--- a/core/res/res/drawable-hdpi/ic_media_previous.png
+++ b/core/res/res/drawable-hdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_stop.png b/core/res/res/drawable-hdpi/ic_media_stop.png
index ec0c1ea..a0ff136 100644
--- a/core/res/res/drawable-hdpi/ic_media_stop.png
+++ b/core/res/res/drawable-hdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_focused_holo.9.png b/core/res/res/drawable-hdpi/list_focused_holo.9.png
index 516f5c7..5552708 100644
--- a/core/res/res/drawable-hdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
index 9ff4cce..5717bee 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
index a556e00..e874330 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
index 9353511..96a6c8a 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
index 9353511..96a6c8a 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
index 2ca591f..4631d85 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
index 1275a2f..39c7af4 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
index df374c4..b06017e 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
index d6b9c67..a1000f8 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
index 69474e3..b3d6706 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
index 69474e3..b3d6706 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
index a2fc32a..9ee35c7 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
index c4b58b7..4da4fa7 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png
index 455fec1..c39d3a8 100644
--- a/core/res/res/drawable-hdpi/presence_away.png
+++ b/core/res/res/drawable-hdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark.9.png
new file mode 100644
index 0000000..cbd8c5c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light.9.png
new file mode 100644
index 0000000..f7f4ba3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
index db23635..a82e7ac 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
index 269a456..db4ce80 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
index d997b36..0c689ff 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
index 8ed5eb7..f3999204 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
index b306f22..eb28ff9 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
index 21cf17e..d281adb 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
index b9833f3..b298586 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
index f68b662..4215396 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
index a76f4ab..a280eab 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
index ecfe9cc..f8d619b 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
index 51a5226..955a2f3 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
index a24da91..6c22e22 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
index 09fc9c3..34a88df 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
index bb257b9..b03842d 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png
index df49a4d..2d306d9 100644
--- a/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png
index a6cb992..720c417 100644
--- a/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png
index 09f8cef..b038fba 100644
--- a/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png
index 58c67a0..ccffda9 100644
--- a/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
index a472338..f638d5e 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png
index ed9f6f6..0aedd25 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_light.9.png
Binary files differ
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/drawable-hdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png
index e886812..f2196fd 100644
--- a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png
index 3e92cf0..f111d82 100644
--- a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png
index 962cefb..4e2ae0f 100644
--- a/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png
index e05b345..479e504 100644
--- a/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
index 0bce767..2fc475b 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png
index 3b9c048..5adecf1 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png
index a4bd074..457fa84 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png
index 587bf4e..c3cfc29 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png
index a86be03..d0e1806 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png
index e3b0729..c30506d 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png
index 4b56420..9106687 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png
index 741674d..2bdda56 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
index 2aad23c..0e5f1e2 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 74ed9b5..38d00db 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 74ed9b5..38d00db 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index abf6493..85c2c4f 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index 3b5d850..4a6351a 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index 3b5d850..4a6351a 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index 71b052b..89d7a0e 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index 215002b..39950f6 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index 215002b..39950f6 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index 87c62ff..0895d57 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index dd8ee9d..54c6354 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
index dd8ee9d..50070ed 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index 51821fa..6a1b6a1 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
index 2ca4c3b..13a1fdd 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
index 2ca4c3b..13a1fdd 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 0fa2859..88da06e 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index bdc0330..88da06e 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
index 35aca07..ae2c2c4 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
index 3a07479..ae2c2c4 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
index 5755584..db0f9ab 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
index b0af68f..db0f9ab 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
index 7c725b2..7abaf3e 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
index 93696aa..7abaf3e 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
index 6dc4f1e..354fd0e 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
index 3a7e25c..354fd0e 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index 5ddcc42..d311c80 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index 5ddcc42..d311c80 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
index 6f19f49..d0fd585 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
index 6f19f49..d0fd585 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
index 1087fe3..e27b3de 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
index 1087fe3..e27b3de 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
index 7db7486..cbed62f 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
index 7db7486..cbed62f 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
index 842d967f..16fa332 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
index 842d967f..16fa332 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
index acef506..fcd73d9 100644
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png
index 548ba02..3e6b2a1 100644
--- a/core/res/res/drawable-mdpi/ic_media_pause.png
+++ b/core/res/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png
index 0fe6806..7966bbc 100644
--- a/core/res/res/drawable-mdpi/ic_media_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
index 940d6a4..b653d05 100644
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_stop.png b/core/res/res/drawable-mdpi/ic_media_stop.png
index 24bcb70..8ea7efee 100644
--- a/core/res/res/drawable-mdpi/ic_media_stop.png
+++ b/core/res/res/drawable-mdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_focused_holo.9.png b/core/res/res/drawable-mdpi/list_focused_holo.9.png
index 7c0599e..00f05d8 100644
--- a/core/res/res/drawable-mdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
index 7d9637a..50f6e98 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
index f7409e4..67434f6 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
index 081ea4e..eb16f8d 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
index 081ea4e..eb16f8d 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
index 739a8d7..58a3b64 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
index bd440f2..382943b 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
index 0318c5f..bc5e3fa 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
index 0318c5f..bc5e3fa 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark.9.png
new file mode 100644
index 0000000..d12a196
--- /dev/null
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light.9.png
new file mode 100644
index 0000000..27c7977
--- /dev/null
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
index 84d4c11..99c42c5 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
index d922ef1..886b044 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
index 8c37c8d..eee058f 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
index e442c28..1ac24be 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
index 9c99bda..29aff4d 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
index 81b205a..4055f70 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
index 3ad6687..ea4ee04 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
index fab4c67..f74c02b 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
index f3ef482..09a2992 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
index d677278..6536ee6 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
index 6255e2e..202b5b7 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
index 1085248..6de0ba8 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
index f88dcba..48af192 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
index c75eece..b3180cb 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png
index eb23155..22eddd8 100644
--- a/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png
index 4318af5..dad0ec9a 100644
--- a/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png
index dc8f01e..2cdd273 100644
--- a/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png
index 7d3af87..f605db8 100644
--- a/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
index 2f00be8..a699924 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png
index 9c48ced..f3c12d7 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png
index a161b03..76ccb8e 100644
--- a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png
index c637dd1..1e56c32 100644
--- a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png
index 680d1a0..914e433 100644
--- a/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png
index 70da7b3..89b0273 100644
--- a/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
index 3d786c0..0787d16 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png
index 2bad2b8..0157e68 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png
index f6ed0bf..51b14d0 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png
index a430b77..d68568a 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png
index 6312c59..6bf153a 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png
index 2086722..0d98983 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png
index e44b1d8..3cee7b8 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png
index ee7e37b..43a7c4c 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
index 91332b1..d23114d 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
index b534256..b7707c6f 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
index b534256..b7707c6f 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
index aca0a23..2ed6386 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
index 137d726..ffee5e2 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
index 137d726..ffee5e2 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
index 7dc088a..702ebc6 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
index c5bc3ec..30bfa30 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
index c5bc3ec..30bfa30 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
index a97c1d3..89ce2df 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
index ed7e0f4..745d53e 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
index ed7e0f4..c509934 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
index 25d139a..b1eab79 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
index 61f5f6f..417152b 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
index 61f5f6f..417152b 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 18aeac6..c271216 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 471b6ea..c271216 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
index 393f967..a2d3ecd 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
index 87193af..a2d3ecd 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
index 0ad8f35..80cbb05 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
index fc21be1..80cbb05 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
index 5ff338d..db2cfc5 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
index 1321473..db2cfc5 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
index 9c914b0..5086f46 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
index fe28238..5086f46 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index 455fdb4..0f5851b 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index 455fdb4..0f5851b 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
index ee8329df..74c853f 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
index ee8329df..74c853f 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
index ccfb2d0..7bd7af5 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
index ccfb2d0..7bd7af5 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
index ad1f4f0..71dad92 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
index ad1f4f0..71dad92 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
index 97304af..1f62eff 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
index 97304af..1f62eff 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_next.png b/core/res/res/drawable-xhdpi/ic_media_next.png
index 726fee7..4def965 100644
--- a/core/res/res/drawable-xhdpi/ic_media_next.png
+++ b/core/res/res/drawable-xhdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_pause.png b/core/res/res/drawable-xhdpi/ic_media_pause.png
index 8614bff..6bd3d48 100644
--- a/core/res/res/drawable-xhdpi/ic_media_pause.png
+++ b/core/res/res/drawable-xhdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_play.png b/core/res/res/drawable-xhdpi/ic_media_play.png
index d93e824..ccfef18 100644
--- a/core/res/res/drawable-xhdpi/ic_media_play.png
+++ b/core/res/res/drawable-xhdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_previous.png b/core/res/res/drawable-xhdpi/ic_media_previous.png
index 59f994d..c4472ae 100644
--- a/core/res/res/drawable-xhdpi/ic_media_previous.png
+++ b/core/res/res/drawable-xhdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_stop.png b/core/res/res/drawable-xhdpi/ic_media_stop.png
index 00159aa..89f36950 100644
--- a/core/res/res/drawable-xhdpi/ic_media_stop.png
+++ b/core/res/res/drawable-xhdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_focused_holo.9.png b/core/res/res/drawable-xhdpi/list_focused_holo.9.png
index 690cb1e..b545f8e 100644
--- a/core/res/res/drawable-xhdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark.9.png
new file mode 100644
index 0000000..6927834
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light.9.png
new file mode 100644
index 0000000..4bce527
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
index 9cf9173..99dbfcc 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
index c8d8a17..2d3e5c8 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
index e3793f7..75c5996 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
index c0be34f0..a2d6ca1 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
index 5e7551d..d8929fc 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
index f4586f8..9174c4e 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
index 86d369d..3015d30 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
index 1c4983b..126637d 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
index edf2573..d45c7a8 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
index 3a16579..29036b90 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
index 5253673..2cb34d7 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
index cfb4a9c..82f752f 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png
index fab743d..e94ce80 100644
--- a/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png
index 9987f74..f006541 100644
--- a/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png
index 6dcd2d4..7bfab99 100644
--- a/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png
index bfddedb..1edcc81 100644
--- a/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png
index eb1e1b7..ff7b959 100644
--- a/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png
index 00c440c..156b5ab 100644
--- a/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png
index 28d170f..d0ce6e4 100644
--- a/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png
index d61be5d..9e9617e 100644
--- a/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png
index 911acd7..b23070c 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png
index 8ba0f75..29f177a 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png
index e30e34d..e85103d 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png
index b1f5b24..75978bc 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
index ea53b5f..a0e6b20 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png
index 8a4b61a..88235fe 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png
index 6a280dc..04fb9a1 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png
index 34a9304..06a14f3 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png
index 757fdd4..af7d631 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png
index 8873ccc..d6ab3ea 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png
index d22226e..5a8e807 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png
index c94248c..392f3dc 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
index c477cf1..95b542d 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable/quickcontact_badge_overlay_dark.xml b/core/res/res/drawable/quickcontact_badge_overlay_dark.xml
index 972488d..6bd7403 100644
--- a/core/res/res/drawable/quickcontact_badge_overlay_dark.xml
+++ b/core/res/res/drawable/quickcontact_badge_overlay_dark.xml
@@ -16,13 +16,13 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item
-        android:state_focused="false"
-        android:state_selected="false"
-        android:state_pressed="false"
-        android:drawable="@drawable/quickcontact_badge_overlay_normal_dark" />
-
-    <item
         android:state_pressed="true"
         android:drawable="@drawable/quickcontact_badge_overlay_pressed_dark" />
+    <item
+        android:state_pressed="false"
+        android:state_focused="true"
+        android:drawable="@drawable/quickcontact_badge_overlay_focused_dark" />
+    <item
+        android:drawable="@drawable/quickcontact_badge_overlay_normal_dark" />
 
 </selector>
diff --git a/core/res/res/drawable/quickcontact_badge_overlay_light.xml b/core/res/res/drawable/quickcontact_badge_overlay_light.xml
index bf95d52..cf7f916 100644
--- a/core/res/res/drawable/quickcontact_badge_overlay_light.xml
+++ b/core/res/res/drawable/quickcontact_badge_overlay_light.xml
@@ -16,13 +16,13 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item
-        android:state_focused="false"
-        android:state_selected="false"
-        android:state_pressed="false"
-        android:drawable="@drawable/quickcontact_badge_overlay_normal_light" />
-
-    <item
         android:state_pressed="true"
         android:drawable="@drawable/quickcontact_badge_overlay_pressed_light" />
+    <item
+        android:state_pressed="false"
+        android:state_focused="true"
+        android:drawable="@drawable/quickcontact_badge_overlay_focused_light" />
+    <item
+        android:drawable="@drawable/quickcontact_badge_overlay_normal_light" />
 
 </selector>
diff --git a/core/res/res/drawable/tab_indicator_ab_holo.xml b/core/res/res/drawable/tab_indicator_ab_holo.xml
new file mode 100644
index 0000000..d8a5750
--- /dev/null
+++ b/core/res/res/drawable/tab_indicator_ab_holo.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@color/transparent" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/tab_selected_holo" />
+
+    <!-- Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/list_focused_holo" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_holo" />
+
+    <!-- Pressed -->
+    <!--    Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/list_pressed_holo_dark" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_holo" />
+
+    <!--    Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_holo" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_holo" />
+</selector>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index ee1ce5f..b58f081 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -50,20 +50,56 @@
             android:layout_centerVertical="true"
             android:layout_marginRight="155dip">
 
-            <!-- Password entry field -->
-            <EditText android:id="@+id/passwordEntry"
-                android:layout_height="wrap_content"
+
+            <LinearLayout
+                android:orientation="horizontal"
                 android:layout_width="match_parent"
-                android:singleLine="true"
-                android:textStyle="normal"
-                android:inputType="textPassword"
-                android:gravity="center"
-                android:textSize="24sp"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:background="@drawable/lockscreen_password_field_dark"
-                android:textColor="#ffffffff"
-                android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
-                />
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:background="@drawable/lockscreen_password_field_dark">
+
+                <EditText android:id="@+id/passwordEntry"
+                    android:layout_height="wrap_content"
+                    android:layout_width="0dip"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:layout_gravity="center"
+                    android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+                    android:singleLine="true"
+                    android:textStyle="normal"
+                    android:inputType="textPassword"
+                    android:textSize="24sp"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:background="@null"
+                    android:textColor="#ffffffff"
+                    android:imeOptions="flagNoFullscreen|actionDone"
+                    android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
+                    />
+
+                <!-- This delete button is only visible for numeric PIN entry -->
+                <ImageButton android:id="@+id/pinDel"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:src="@android:drawable/ic_input_delete"
+                    android:clickable="true"
+                    android:padding="8dip"
+                    android:layout_gravity="center"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:visibility="gone"
+                    />
+
+                <ImageView android:id="@+id/switch_ime_button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:src="@drawable/ic_lockscreen_ime"
+                    android:clickable="true"
+                    android:padding="8dip"
+                    android:layout_gravity="center"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:visibility="gone"
+                    />
+
+            </LinearLayout>
 
             <!-- Numeric keyboard -->
             <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
@@ -71,7 +107,7 @@
                 android:layout_height="330dip"
                 android:background="#40000000"
                 android:layout_marginTop="5dip"
-                android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+                android:keyBackground="@drawable/btn_keyboard_key_ics"
                 android:visibility="gone"
             />
         </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index 254dd3e..cadb5f8 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -44,22 +44,56 @@
         android:gravity="center">
 
         <!-- Password entry field -->
-        <EditText android:id="@+id/passwordEntry"
-            android:layout_height="wrap_content"
+        <LinearLayout
+            android:orientation="horizontal"
             android:layout_width="330dip"
-            android:singleLine="true"
-            android:textStyle="normal"
-            android:inputType="textPassword"
-            android:gravity="center"
+            android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:textSize="24sp"
             android:layout_marginTop="120dip"
             android:layout_marginBottom="5dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:background="@drawable/lockscreen_password_field_dark"
-            android:textColor="#ffffffff"
-            android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
-            />
+            android:background="@drawable/lockscreen_password_field_dark">
+
+            <EditText android:id="@+id/passwordEntry"
+                android:layout_height="wrap_content"
+                android:layout_width="0dip"
+                android:layout_weight="1"
+                android:singleLine="true"
+                android:textStyle="normal"
+                android:inputType="textPassword"
+                android:gravity="center"
+                android:layout_gravity="center"
+                android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+                android:textSize="24sp"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:background="@null"
+                android:textColor="#ffffffff"
+                android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
+                />
+
+            <!-- This delete button is only visible for numeric PIN entry -->
+            <ImageButton android:id="@+id/pinDel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:src="@android:drawable/ic_input_delete"
+                android:clickable="true"
+                android:padding="8dip"
+                android:layout_gravity="center"
+                android:background="?android:attr/selectableItemBackground"
+                android:visibility="gone"
+                />
+
+            <ImageView android:id="@+id/switch_ime_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:src="@drawable/ic_lockscreen_ime"
+                android:clickable="true"
+                android:padding="8dip"
+                android:layout_gravity="center"
+                android:background="?android:attr/selectableItemBackground"
+                android:visibility="gone"
+                />
+
+        </LinearLayout>
 
         <View
             android:layout_width="match_parent"
@@ -72,7 +106,7 @@
             android:layout_width="330dip"
             android:layout_height="260dip"
             android:background="#40000000"
-            android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+            android:keyBackground="@drawable/btn_keyboard_key_ics"
             android:layout_marginBottom="80dip"
         />
 
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/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 62f59f6..ba0c22f 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -143,6 +143,8 @@
             android:layout_width="0dip"
             android:layout_weight="1"
             android:gravity="center"
+            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
+            android:layout_gravity="center_vertical"
             android:singleLine="true"
             android:textStyle="normal"
             android:inputType="textPassword"
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 597cfe7..f6933c3 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -109,6 +109,8 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:gravity="center_horizontal"
+            android:layout_gravity="center_vertical"
+            android:layout_marginLeft="@dimen/keyguard_lockscreen_pin_margin_left"
             android:singleLine="true"
             android:textStyle="normal"
             android:inputType="textPassword"
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index f699a46..ca1dc88 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -93,7 +93,7 @@
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:background="@null"
-                android:inputType="text|textAutoComplete"
+                android:inputType="text|textAutoComplete|textNoSuggestions"
                 android:imeOptions="actionSearch"
                 android:dropDownHeight="wrap_content"
                 android:dropDownAnchor="@id/search_edit_frame"
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 269e348..24802e2 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1169,8 +1169,7 @@
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Тих режим"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Включване на звука"</string>
-    <!-- no translation found for description_target_unlock_tablet (3833195335629795055) -->
-    <skip />
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прокарайте пръст, за да отключите."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="5913502399391940888">"Включете слушалки, за да чуете клавишите за паролата на висок глас."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Придвижване към „Начало“"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 788b285..97ad227 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1169,8 +1169,7 @@
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Lydløs"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Lyd slået til"</string>
-    <!-- no translation found for description_target_unlock_tablet (3833195335629795055) -->
-    <skip />
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glid hurtigt henover for at låse op."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="5913502399391940888">"Tilslut et headset for at få læst taster højt, når du indtaster en adgangskode."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Naviger hjem"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 71c6da5..b4a3c92 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -282,7 +282,7 @@
     <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linux-Signale an Apps senden"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Ermöglicht der App, das Senden des gelieferten Signals an alle anhaltenden Prozesse zu fordern"</string>
     <string name="permlab_persistentActivity" msgid="8659652042401085862">"Apps permanent ausführen"</string>
-    <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Ermöglicht einer App, eigene Komponenten persistent zu machen, damit das System diese nicht für andere Anwendungen nutzen kann"</string>
+    <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Ermöglicht einer App, eigene Komponenten permanent zu machen, damit das System diese nicht für andere Apps nutzen kann"</string>
     <string name="permlab_deletePackages" msgid="3343439331576348805">"Apps löschen"</string>
     <string name="permdesc_deletePackages" msgid="3634943677518723314">"Ermöglicht einer App, Android-Pakete zu löschen. Schädliche Anwendungen können so wichtige Anwendungen löschen."</string>
     <string name="permlab_clearAppUserData" msgid="2192134353540277878">"Daten anderer Apps löschen"</string>
@@ -340,7 +340,7 @@
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"Ohne das Wissen der Eigentümer Kalendertermine hinzufügen oder ändern und E-Mails an Gäste senden"</string>
     <string name="permdesc_writeCalendar" msgid="5368129321997977226">"Ermöglicht einer App das Senden von Termineinladungen als Kalendereigentümer und das Hinzufügen, Entfernen und Ändern von Terminen, die Sie auf Ihrem Gerät bearbeiten können, einschließlich der Termine von Freunden oder Kollegen. Schädliche Apps mit dieser Berechtigung können Spam-E-Mails senden, die von Kalendereigentümern zu kommen scheinen, Termine ohne das Wissen der Eigentümer ändern oder falsche Termine hinzufügen."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"Simulierte Standortquellen für Testzwecke"</string>
-    <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Erstellt falsche Standortquellen für Testzwecke. Schädliche Anwendungen können so den von den echten Standortquellen wie GPS oder Netzwerkanbieter zurückgegebenen Standort und/oder Status überschreiben."</string>
+    <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Erstellt simulierte Standortquellen für Testzwecke. Schädliche Anwendungen können so den von den echten Standortquellen wie GPS oder Netzwerkanbieter zurückgegebenen Standort und/oder Status überschreiben."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"Zugriff auf zusätzliche Dienstanbieterbefehle für Standort. Schädliche Anwendungen könnten so die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"Berechtigung zur Installation eines Standortanbieters"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index dfc0916..5896467 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -151,7 +151,7 @@
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Sound is OFF"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Sound is ON"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
-    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aiplane mode is ON"</string>
+    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Airplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Airplane mode is OFF"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f24e64c..f7dd60b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1169,7 +1169,7 @@
     <string name="description_target_camera" msgid="969071997552486814">"دوربین"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ساکت"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"صدا روشن"</string>
-    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"برای بازگشایی قفل، انگشت خود را روی صفحه بلغزانید."</string>
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"برای بازگشایی قفل، بلغزانید."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="5913502399391940888">"برای شنیدن کلیدهای گذرواژه که با صدای بلند خوانده می‌شوند، از هدست استفاده کنید."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطه."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"رفتن به صفحه اصلی"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 3c90e09..4985388 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1169,8 +1169,7 @@
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparat"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Bešumno"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Zvuk je uključen"</string>
-    <!-- no translation found for description_target_unlock_tablet (3833195335629795055) -->
-    <skip />
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Prijeđite prstima da biste otključali."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="5913502399391940888">"Priključite slušalice da biste čuli tipke zaporke izgovorene naglas."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Točka."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Kreni na početnu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 2fd2cfc..0169ea2 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -632,7 +632,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Irmã"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Cônjuge"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Página inicial"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Residência"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Emprego"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Outro"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduzir código PIN"</string>
@@ -1014,7 +1014,7 @@
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatar"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
     <string name="adb_active_notification_message" msgid="8470296818270110396">"Seleccione para desactivar depuração USB."</string>
-    <string name="select_input_method" msgid="6865512749462072765">"Seleccionar método de entrada"</string>
+    <string name="select_input_method" msgid="6865512749462072765">"Selecionar método de entrada"</string>
     <string name="configure_input_methods" msgid="6324843080254191535">"Configurar métodos de entrada"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 3670e53..6334bcd 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1169,8 +1169,7 @@
     <string name="description_target_camera" msgid="969071997552486814">"Cameră foto"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silenţios"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Sunet activat"</string>
-    <!-- no translation found for description_target_unlock_tablet (3833195335629795055) -->
-    <skip />
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisaţi pentru a debloca."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="5913502399391940888">"Conectaţi un set căşti-microfon pentru a auzi tastele apăsate când introduceţi parola."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punct."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigaţi la ecranul de pornire"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 24269e7..d66c2d4 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1080,7 +1080,7 @@
     <string name="submit" msgid="1602335572089911941">"Отправить"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Включен режим \"Штурман\""</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Чтобы выйти, нажмите здесь."</string>
-    <string name="tethered_notification_title" msgid="3146694234398202601">"USB-модем или точка доступа Wi-Fi активны"</string>
+    <string name="tethered_notification_title" msgid="3146694234398202601">"USB-модем/точка доступа Wi-Fi используется"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Нажмите для настройки"</string>
     <string name="back_button_label" msgid="2300470004503343439">"Назад"</string>
     <string name="next_button_label" msgid="1080555104677992408">"Далее"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 157a3fc..da78c17 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1169,8 +1169,7 @@
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Нечујно"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Укључи звук"</string>
-    <!-- no translation found for description_target_unlock_tablet (3833195335629795055) -->
-    <skip />
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Превуците да бисте откључали."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="5913502399391940888">"Укључите слушалице да бисте чули наглас изговорене тастере за лозинку."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Тачка."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Кретање до Почетне"</string>
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/dimens.xml b/core/res/res/values/dimens.xml
index fa18648..82ef68a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -169,6 +169,9 @@
     <!-- Size of top margin on Clock font to edge on unlock LockScreen -->
     <dimen name="keyguard_lockscreen_status_line_clockfont_bottom_margin">12dip</dimen>
 
+    <!-- Padding on left margin of PIN text entry field to center it when del button is showing -->
+    <dimen name="keyguard_lockscreen_pin_margin_left">40dip</dimen>
+
     <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. -->
     <dimen name="activity_chooser_popup_min_width">200dip</dimen>
 
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
old mode 100755
new mode 100644
index a819173..2f40a5a
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1362,6 +1362,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 8d95d86e5..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">
@@ -1823,6 +1824,7 @@
     </style>
 
     <style name="Widget.Holo.Tab" parent="Widget.Holo.ActionBar.TabView">
+        <item name="android:background">@android:drawable/tab_indicator_holo</item>
         <item name="android:layout_width">0dip</item>
         <item name="android:layout_weight">1</item>
         <item name="android:minWidth">80dip</item>
@@ -1910,7 +1912,7 @@
     </style>
 
     <style name="Widget.Holo.ActionBar.TabView" parent="Widget.ActionBar.TabView">
-        <item name="android:background">@drawable/tab_indicator_holo</item>
+        <item name="android:background">@drawable/tab_indicator_ab_holo</item>
         <item name="android:paddingLeft">16dip</item>
         <item name="android:paddingRight">16dip</item>
     </style>
@@ -2277,6 +2279,10 @@
     </style>
 
     <style name="Widget.Holo.Light.Tab" parent="Widget.Holo.Light.ActionBar.TabView">
+        <item name="android:background">@android:drawable/tab_indicator_holo</item>
+        <item name="android:layout_width">0dip</item>
+        <item name="android:layout_weight">1</item>
+        <item name="android:minWidth">80dip</item>
     </style>
 
     <style name="Widget.Holo.Light.ActionBar.TabBar" parent="Widget.Holo.ActionBar.TabBar">
diff --git a/core/res/res/xml-xlarge/password_kbd_numeric.xml b/core/res/res/xml-xlarge/password_kbd_numeric.xml
index 3745672..b2704f6 100755
--- a/core/res/res/xml-xlarge/password_kbd_numeric.xml
+++ b/core/res/res/xml-xlarge/password_kbd_numeric.xml
@@ -49,12 +49,10 @@
     </Row>
 
     <Row android:rowEdgeFlags="bottom">
+        <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0_no_plus"
+             android:keyWidth="66.66%p" android:keyEdgeFlags="left"/>
         <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
-             android:keyEdgeFlags="left"/>
-        <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0_no_plus"/>
-        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
-             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
-             android:isRepeatable="true" android:keyEdgeFlags="right"/>
+             android:keyEdgeFlags="right"/>
     </Row>
 
 </Keyboard>
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/docs/html/guide/topics/admin/device-admin.jd b/docs/html/guide/topics/admin/device-admin.jd
index 7bbf5e6..820c3c0 100644
--- a/docs/html/guide/topics/admin/device-admin.jd
+++ b/docs/html/guide/topics/admin/device-admin.jd
@@ -27,6 +27,12 @@
       <li>{@link android.app.admin.DevicePolicyManager}</li>
       <li>{@link android.app.admin.DeviceAdminInfo}</li>
     </ol>
+    <h2>Related samples</h2>
+    <ol>
+      <li><a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/DeviceAdminSample.html">
+DeviceAdminSample</a></li>
+</ol>
 </div>
 </div>
 
@@ -201,6 +207,16 @@
 <td>Specifies that the storage area should be encrypted, if the device supports it. 
 Introduced in Android 3.0.</td> </tr>
 
+<tr>
+  <td>Disable camera</td>
+  
+  <td>Specifies that the camera should be disabled. Note that this doesn't have
+to be a permanent disabling. The camera can be enabled/disabled dynamically
+based on context, time, and so on. Introduced in Android 4.0.</td>
+  
+</tr>
+
+
 </table>
 
 <h4>Other features</h4>
@@ -247,6 +263,7 @@
 locks.</li>
   <li>Make the device lock immediately.</li>
   <li>Wipe the device's data (that is, restore factory settings).</li>
+  <li>Disable the camera.</li>
   
 </ul>
 
@@ -280,46 +297,38 @@
   <li>A declaration of security policies used in metadata.</li>
 </ul>
 <p>Here is an excerpt from the Device Administration sample manifest:</p>
-<pre>&lt;activity android:name=&quot;.app.DeviceAdminSample$Controller&quot;
-          android:label=&quot;&#64;string/activity_sample_device_admin&quot;&gt;
-    &lt;intent-filter&gt;
-        &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
-        &lt;category android:name=&quot;android.intent.category.SAMPLE_CODE&quot; /&gt;
-    &lt;/intent-filter&gt;
+<pre>&lt;activity android:name=&quot;.app.DeviceAdminSample&quot;
+            android:label=&quot;&#64;string/activity_sample_device_admin&quot;&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
+        &lt;category android:name=&quot;android.intent.category.SAMPLE_CODE&quot; /&gt;
+    &lt;/intent-filter&gt;
 &lt;/activity&gt;
-
-&lt;receiver android:name=&quot;.app.DeviceAdminSample&quot;
-          android:label=&quot;&#64;string/sample_device_admin&quot;
-          android:description=&quot;&#64;string/sample_device_admin_description&quot;
-          android:permission=&quot;android.permission.BIND_DEVICE_ADMIN&quot;&gt;
-    &lt;meta-data android:name=&quot;android.app.device_admin&quot;
-               android:resource=&quot;&#64;xml/device_admin_sample&quot; /&gt;
-    &lt;intent-filter&gt;
-        &lt;action android:name=&quot;android.app.action.DEVICE_ADMIN_ENABLED&quot; /&gt;
-    &lt;/intent-filter&gt;
+&lt;receiver android:name=&quot;.app.DeviceAdminSample$DeviceAdminSampleReceiver&quot;
+        android:label=&quot;&#64;string/sample_device_admin&quot;
+        android:description=&quot;&#64;string/sample_device_admin_description&quot;
+        android:permission=&quot;android.permission.BIND_DEVICE_ADMIN&quot;&gt;
+    &lt;meta-data android:name=&quot;android.app.device_admin&quot;
+            android:resource=&quot;&#64;xml/device_admin_sample&quot; /&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name=&quot;android.app.action.DEVICE_ADMIN_ENABLED&quot; /&gt;
+    &lt;/intent-filter&gt;
 &lt;/receiver&gt;</pre>
 
  <p>Note that:</p>
 <ul>
-  <li>The activity in the sample application is an {@link android.app.Activity}
-subclass called <code>Controller</code>. The syntax
-<code>&quot;.app.DeviceAdminSample$Controller&quot;</code>  indicates that
-<code>Controller</code> is an inner class that is nested inside the
-<code>DeviceAdminSample</code> class. Note that an Activity does not need to be
-an inner class; it just is in this example.</li>
-
 <li>The following attributes refer to string resources that for the sample application reside in
 <code>ApiDemos/res/values/strings.xml</code>. For more information about resources, see
 <a
 href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.
 <ul>
-<li><code>android:label=&quot;@string/activity_sample_device_admin&quot;</code> refers to the
+<li><code>android:label=&quot;&#64;string/activity_sample_device_admin&quot;</code> refers to the
 user-readable label for the activity.</li>
 
-<li><code>android:label=&quot;@string/sample_device_admin&quot;</code> refers to the
+<li><code>android:label=&quot;&#64;string/sample_device_admin&quot;</code> refers to the
 user-readable label for the permission.</li>
 
-<li><code>android:description=&quot;@string/sample_device_admin_description&quot;</code> refers to
+<li><code>android:description=&quot;&#64;string/sample_device_admin_description&quot;</code> refers to
 the user-readable description of the permission. A descripton is typically longer and more
 informative than
 a label.</li>
@@ -357,6 +366,9 @@
     &lt;reset-password /&gt;
     &lt;force-lock /&gt;
     &lt;wipe-data /&gt;
+    &lt;expire-password /&gt;
+    &lt;encrypted-storage /&gt;
+    &lt;disable-camera /&gt;
   &lt;/uses-policies&gt;
 &lt;/device-admin&gt;
 </pre>
@@ -401,33 +413,34 @@
 events. For example:</p>
 <pre>public class DeviceAdminSample extends DeviceAdminReceiver {
 
-...
+    void showToast(Context context, String msg) {
+        String status = context.getString(R.string.admin_receiver_status, msg);
+        Toast.makeText(context, status, Toast.LENGTH_SHORT).show();
+    }
+
     &#64;Override
-    public void onEnabled(Context context, Intent intent) {
-        showToast(context, &quot;Sample Device Admin: enabled&quot;);
-    }
+    public void onEnabled(Context context, Intent intent) {
+        showToast(context, context.getString(R.string.admin_receiver_status_enabled));
+    }
 
-    &#64;Override
-    public CharSequence onDisableRequested(Context context, Intent intent) {
-        return &quot;This is an optional message to warn the user about disabling.&quot;;
-    }
+    &#64;Override
+    public CharSequence onDisableRequested(Context context, Intent intent) {
+        return context.getString(R.string.admin_receiver_status_disable_warning);
+    }
 
-    &#64;Override
-    public void onDisabled(Context context, Intent intent) {
-        showToast(context, &quot;Sample Device Admin: disabled&quot;);
-    }
+    &#64;Override
+    public void onDisabled(Context context, Intent intent) {
+        showToast(context, context.getString(R.string.admin_receiver_status_disabled));
+    }
 
-    &#64;Override
-    public void onPasswordChanged(Context context, Intent intent) {
-        showToast(context, &quot;Sample Device Admin: pw changed&quot;);
-    }
-
-    void showToast(Context context, CharSequence msg) {
-        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
+    &#64;Override
+    public void onPasswordChanged(Context context, Intent intent) {
+        showToast(context, context.getString(R.string.admin_receiver_status_pw_changed));
     }
 ...
 }</pre>
 
+
 <h4 id="enabling">Enabling the application</h4>
 <p>One of the major events a device admin application has to handle is the user
 enabling the application. The user must explicitly enable the application for
@@ -438,43 +451,50 @@
 action that triggers the {@link android.app.admin.DevicePolicyManager#ACTION_ADD_DEVICE_ADMIN}
 intent. In the
 sample application, this happens when the user clicks the <strong>Enable
-Admin</strong> button. </p>
-<p>When the user clicks the <strong>Enable Admin</strong> button, the display
-changes to prompt the user to enable the device admin application, as shown in figure
+Admin</strong> checkbox. </p>
+<p>When the user clicks the <strong>Enable Admin</strong> checkbox, the display
+changes to prompt the user to activate the device admin application, as shown in figure
 2.</p>
 
 <img src="{@docRoot}images/admin/device-admin-activate-prompt.png"/>
 <p class="img-caption"><strong>Figure 2.</strong> Sample Application: Activating the Application</p>
-<p>Below  is the code that gets executed when the user clicks the <strong>Enable
-Admin</strong> button shown in figure 1. </p>
 
-<pre> private OnClickListener mEnableListener = new OnClickListener() {
-    public void onClick(View v) {
-        // Launch the activity to have the user enable our admin.
-        Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
-        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
-               mDeviceAdminSample);
-        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
-               &quot;Additional text explaining why this needs to be added.&quot;);
-        startActivityForResult(intent, RESULT_ENABLE);
-    }
-};
+<p>Below  is the code that gets executed when the user clicks the <strong>Enable Admin</strong> checkbox. This has the effect of triggering the 
+{@link android.preference.Preference.OnPreferenceChangeListener#onPreferenceChange(android.preference.Preference, java.lang.Object) onPreferenceChange()} 
+callback. This callback is invoked when the value of this  {@link android.preference.Preference} has been changed by the user and is about to be set and/or persisted. If the user is enabling the application, the display
+changes to prompt the user to activate the device admin application, as shown in figure
+2. Otherwise, the device admin application is disabled. </p>
 
-...
-// This code checks whether the device admin app was successfully enabled.
-&#64;Override
-protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-    switch (requestCode) {
-        case RESULT_ENABLE:
-            if (resultCode == Activity.RESULT_OK) {
-                Log.i(&quot;DeviceAdminSample&quot;, &quot;Administration enabled!&quot;);
-            } else {
-                Log.i(&quot;DeviceAdminSample&quot;, &quot;Administration enable FAILED!&quot;);
-            }
-            return;
-    }
-    super.onActivityResult(requestCode, resultCode, data);
-}</pre>
+<pre>&#64;Override
+        public boolean onPreferenceChange(Preference preference, Object newValue) {
+            if (super.onPreferenceChange(preference, newValue)) {
+                return true;
+            }
+            boolean value = (Boolean) newValue;
+            if (preference == mEnableCheckbox) {
+                if (value != mAdminActive) {
+                    if (value) {
+                        // Launch the activity to have the user enable our admin.
+                        Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
+                        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample);
+                        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
+                                mActivity.getString(R.string.add_admin_extra_app_text));
+                        startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
+                        // return false - don't update checkbox until we're really active
+                        return false;
+                    } else {
+                        mDPM.removeActiveAdmin(mDeviceAdminSample);
+                        enableDeviceCapabilitiesArea(false);
+                        mAdminActive = false;
+                    }
+                }
+            } else if (preference == mDisableCameraCheckbox) {
+                mDPM.setCameraDisabled(mDeviceAdminSample, value);
+                ...
+            }
+            return true;
+        }</pre>
+
 
 <p>The line
 <code>intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
@@ -489,18 +509,17 @@
 {@link android.app.admin.DevicePolicyManager#isAdminActive(android.content.ComponentName) isAdminActive()}. Notice that the {@link android.app.admin.DevicePolicyManager}
 method {@link android.app.admin.DevicePolicyManager#isAdminActive(android.content.ComponentName) isAdminActive()} takes a {@link android.app.admin.DeviceAdminReceiver}
 component as its argument:</p>
+
 <pre>
 DevicePolicyManager mDPM;
 ...
-boolean active = mDPM.isAdminActive(mDeviceAdminSample);
-if (active) {
-    // Admin app is active, so do some admin stuff
-               ...
-} else {
-    // do something else
+private boolean isActiveAdmin() {
+    return mDPM.isAdminActive(mDeviceAdminSample);
 }
 </pre>
 
+
+
 <h3 id="admin_ops">Managing policies</h3>
 <p>{@link android.app.admin.DevicePolicyManager} is a public class for managing policies
 enforced on a device. {@link android.app.admin.DevicePolicyManager} manages policies for one
@@ -618,49 +637,6 @@
 ...
 mDPM.setPasswordExpirationTimeout(mDeviceAdminSample, pwExpiration);
 </pre>
-
-<p>From the <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/DeviceAdminSample.html"
->Device Administration API sample</a>, here is the code
-that updates the password expiration status:</p>
-
-<pre>
-DevicePolicyManager mDPM;
-ComponentName mDeviceAdminSample;
-private TextView mPasswordExpirationStatus;
-...
-void updatePasswordExpirationStatus() {
-    boolean active = mDPM.isAdminActive(mDeviceAdminSample);
-    String statusText;
-    if (active) {
-        long now = System.currentTimeMillis();
-        // Query the DevicePolicyManager twice - first for the expiration values
-        // set by the sample app, and later, for the system values (which may be different
-        // if there is another administrator active.)
-        long expirationDate = mDPM.getPasswordExpiration(mDeviceAdminSample);
-        long mSecUntilExpiration = expirationDate - now;
-        if (mSecUntilExpiration &gt;= 0) {
-            statusText = &quot;Expiration in &quot; + countdownString(mSecUntilExpiration);
-        } else {
-            statusText = &quot;Expired &quot; + countdownString(-mSecUntilExpiration) + &quot; ago&quot;;
-        }
-
-        // expirationTimeout is the cycle time between required password refresh
-        long expirationTimeout = mDPM.getPasswordExpirationTimeout(mDeviceAdminSample);
-        statusText += &quot; / timeout period &quot; + countdownString(expirationTimeout);
-
-        // Now report the aggregate (global) expiration time
-        statusText += &quot; / Aggregate &quot;;
-        expirationDate = mDPM.getPasswordExpiration(null);
-        mSecUntilExpiration = expirationDate - now;
-        if (mSecUntilExpiration &gt;= 0) {
-            statusText += &quot;expiration in &quot; + countdownString(mSecUntilExpiration);
-        } else {
-            statusText += &quot;expired &quot; + countdownString(-mSecUntilExpiration) + &quot; ago&quot;;
-        }
-    } else {
-        statusText = &quot;&lt;inactive&gt;&quot;;
-    }
-    mPasswordExpirationStatus.setText(statusText);</pre>
     
 <h5 id="history">Restrict password based on history</h5>
 
@@ -718,6 +694,19 @@
 <p>The {@link android.app.admin.DevicePolicyManager#wipeData wipeData()} method takes as its parameter a bit mask of
 additional options. Currently the value must be 0. </p>
 
+<h4>Disable camera</h4>
+<p>Beginning with Android 4.0, you can disable the camera. Note that this doesn't have to be a permanent disabling. The camera can be enabled/disabled dynamically based on context, time, and so on. </p>
+<p>You control whether the camera is disabled by using the 
+{@link android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean) setCameraDisabled()} method. For example, this snippet sets the camera to be enabled or disabled based on a checkbox setting:</p>
+
+<pre>private CheckBoxPreference mDisableCameraCheckbox;
+DevicePolicyManager mDPM;
+ComponentName mDeviceAdminSample;
+...
+mDPM.setCameraDisabled(mDeviceAdminSample, mDisableCameraCheckbox.isChecked());<br />
+</pre>
+
+
 <h4 id=storage">Storage encryption</h4>
 <p>Beginning with Android 3.0, you can use the 
 {@link android.app.admin.DevicePolicyManager#setStorageEncryption(android.content.ComponentName,boolean) setStorageEncryption()} 
diff --git a/docs/html/images/admin/device-admin-activate-prompt.png b/docs/html/images/admin/device-admin-activate-prompt.png
index 2851194..3786788 100644
--- a/docs/html/images/admin/device-admin-activate-prompt.png
+++ b/docs/html/images/admin/device-admin-activate-prompt.png
Binary files differ
diff --git a/docs/html/images/admin/device-admin-app.png b/docs/html/images/admin/device-admin-app.png
index c96defc..6b23aba 100644
--- a/docs/html/images/admin/device-admin-app.png
+++ b/docs/html/images/admin/device-admin-app.png
Binary files differ
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index 9089937..07a0e43 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -57,7 +57,7 @@
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A9.2,90.8" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A9.8,90.2" />
 
 <table>
 <tr>
@@ -66,14 +66,14 @@
 </tr>
 <tr>
 <td>1.1</th>
-<td>9.2%</td>
+<td>9.8%</td>
 </tr>
 <tr>
 <td>2.0</th>
-<td>90.8%</td>
+<td>90.2%</td>
 </tr>
 </table>
 
-<p><em>Data collected during a 7-day period ending on October 3, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on November 3, 2011</em></p>
 </div>
 
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 135c6f2..8041096 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -52,7 +52,7 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="470"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:1.1,1.4,11.7,45.3,0.5,38.2,0.2,0.9,0.7&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2&chco=c4df9b,6fad0c" />
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:0.9,1.4,10.7,40.7,0.5,43.9,0.1,0.9,0.9&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2&chco=c4df9b,6fad0c" />
 
 <table>
 <tr>
@@ -61,21 +61,21 @@
   <th>API Level</th>
   <th>Distribution</th>
 </tr>
-<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td>  <td>3</td><td>1.1%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td>  <td>3</td><td>0.9%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td>    <td>4</td><td>1.4%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td>   <td>7</td><td>11.7%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td>    <td>8</td><td>45.3%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td>   <td>7</td><td>10.7%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td>    <td>8</td><td>40.7%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-2.3.html">Android 2.3 -<br/>
                              Android 2.3.2</a></td><td rowspan="2">Gingerbread</td>    <td>9</td><td>0.5%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.3 -<br/>
-      Android 2.3.7</a></td><!-- Gingerbread -->                                       <td>10</td><td>38.2%</td></tr>
+      Android 2.3.7</a></td><!-- Gingerbread -->                                       <td>10</td><td>43.9%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-3.0.html">Android 3.0</a></td>
-                                                   <td rowspan="3">Honeycomb</td>      <td>11</td><td>0.2%</td></tr>
+                                                   <td rowspan="3">Honeycomb</td>      <td>11</td><td>0.1%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>0.9%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>0.7%</td></tr> 
+<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>0.9%</td></tr> 
 </table>
 
-<p><em>Data collected during a 14-day period ending on October 3, 2011</em></p>
+<p><em>Data collected during a 14-day period ending on November 3, 2011</em></p>
 <!--
 <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
 -->
@@ -104,9 +104,9 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C04/01%7C04/15%7C05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.7,99.6,99.6,99.5,99.4,99.3,99.2,99.0,98.8,98.7,98.5,98.5,98.2|97.0,97.1,97.3,97.5,97.5,97.5,97.7,97.6,97.5,97.5,97.5,97.5,97.1|93.5,93.9,94.3,94.8,95.0,95.2,95.5,95.5,95.5,95.6,95.7,95.8,95.6|66.4,68.0,69.8,71.5,73.9,75.4,77.6,79.0,80.2,81.1,82.4,83.3,83.8|2.5,3.1,4.0,6.1,9.5,13.6,17.8,20.6,24.3,27.5,31.2,34.7,38.3|1.7,2.2,3.0,5.1,8.4,12.6,16.8,20.0,23.7,26.9,30.6,34.1,37.8&chm=b,c3df9b,0,1,0|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid 2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|tAndroid 2.3.3,131d02,5,5,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/01%7C10/15%7C11/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.6,99.5,99.4,99.3,99.2,99.0,98.8,98.7,98.5,98.5,98.2,98.1,98.0|97.3,97.5,97.5,97.5,97.7,97.6,97.5,97.5,97.5,97.5,97.1,97.1,97.1|94.3,94.8,95.0,95.2,95.5,95.5,95.5,95.6,95.7,95.8,95.6,95.9,95.7|69.8,71.5,73.9,75.4,77.6,79.0,80.2,81.1,82.4,83.3,83.8,84.9,85.0|4.0,6.1,9.5,13.6,17.8,20.6,24.3,27.5,31.2,34.7,38.3,41.3,44.0|3.0,5.1,8.4,12.6,16.8,20.0,23.7,26.9,30.6,34.1,37.8,40.8,43.5&chm=b,c3df9b,0,1,0|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid 2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|tAndroid 2.3.3,131d02,5,3,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
 
-<p><em>Last historical dataset collected during a 14-day period ending on October 3, 2011</em></p>
+<p><em>Last historical dataset collected during a 14-day period ending on November 3, 2011</em></p>
 
 
 </div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/dashboard/screens.jd b/docs/html/resources/dashboard/screens.jd
index 67b47d0..ec3034d 100644
--- a/docs/html/resources/dashboard/screens.jd
+++ b/docs/html/resources/dashboard/screens.jd
@@ -60,7 +60,7 @@
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A2.6,0.1,3.0,71.9,0.9,17.6,2.7,1.2" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A2.9,0.1,3.1,70.8,1.0,17.7,3.0,1.3" />
 
 <table>
 <tr>
@@ -71,31 +71,31 @@
 <th scope="col">xhdpi</th>
 </tr>
 <tr><th scope="row">small</th> 
-<td>1.2%</td>     <!-- small/ldpi -->
+<td>1.3%</td>     <!-- small/ldpi -->
 <td></td>     <!-- small/mdpi -->
-<td>2.7%</td> <!-- small/hdpi -->
+<td>3.0%</td> <!-- small/hdpi -->
 <td></td>     <!-- small/xhdpi -->
 </tr> 
 <tr><th scope="row">normal</th> 
-<td>0.9%</td>  <!-- normal/ldpi -->
-<td>17.6%</td> <!-- normal/mdpi -->
-<td>71.9%</td> <!-- normal/hdpi -->
+<td>1.0%</td>  <!-- normal/ldpi -->
+<td>17.7%</td> <!-- normal/mdpi -->
+<td>70.8%</td> <!-- normal/hdpi -->
 <td></td>      <!-- normal/xhdpi -->
 </tr> 
 <tr><th scope="row">large</th> 
 <td>0.1%</td>     <!-- large/ldpi -->
-<td>3.0%</td> <!-- large/mdpi -->
+<td>3.1%</td> <!-- large/mdpi -->
 <td></td>     <!-- large/hdpi -->
 <td></td>     <!-- large/xhdpi -->
 </tr> 
 <tr><th scope="row">xlarge</th> 
 <td></td>     <!-- xlarge/ldpi -->
-<td>2.6%</td> <!-- xlarge/mdpi -->
+<td>2.9%</td> <!-- xlarge/mdpi -->
 <td></td>     <!-- xlarge/hdpi -->
 <td></td>     <!-- xlarge/xhdpi -->
 </tr> 
 </table>
 
-<p><em>Data collected during a 7-day period ending on October 3, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on November 3, 2011</em></p>
 </div>
 
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/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index bc7e906..18b8bc7 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -202,18 +202,30 @@
 
     @Override
     public void setAlpha(int alpha) {
+        if (mPaint == null && alpha == 0xFF) {
+            // Fast common case -- leave at normal alpha.
+            return;
+        }
         getPaint().setAlpha(alpha);
         invalidateSelf();
     }
     
     @Override
     public void setColorFilter(ColorFilter cf) {
+        if (mPaint == null && cf == null) {
+            // Fast common case -- leave at no color filter.
+            return;
+        }
         getPaint().setColorFilter(cf);
         invalidateSelf();
     }
 
     @Override
     public void setDither(boolean dither) {
+        if (mPaint == null && dither == DEFAULT_DITHER) {
+            // Fast common case -- leave at default dither.
+            return;
+        }
         getPaint().setDither(dither);
         invalidateSelf();
     }
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 3fa2acb..33b2f00 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -110,7 +110,8 @@
     
     // Place a file descriptor into the parcel.  The given fd must remain
     // valid for the lifetime of the parcel.
-    status_t            writeFileDescriptor(int fd);
+    // The Parcel does not take ownership of the given fd unless you ask it to.
+    status_t            writeFileDescriptor(int fd, bool takeOwnership = false);
     
     // Place a file descriptor into the parcel.  A dup of the fd is made, which
     // will be closed once the parcel is destroyed.
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/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index c7180ce..6b4c1a6 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -710,24 +710,19 @@
     return err;
 }
 
-status_t Parcel::writeFileDescriptor(int fd)
+status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
 {
     flat_binder_object obj;
     obj.type = BINDER_TYPE_FD;
     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
     obj.handle = fd;
-    obj.cookie = (void*)0;
+    obj.cookie = (void*) (takeOwnership ? 1 : 0);
     return writeObject(obj, true);
 }
 
 status_t Parcel::writeDupFileDescriptor(int fd)
 {
-    flat_binder_object obj;
-    obj.type = BINDER_TYPE_FD;
-    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj.handle = dup(fd);
-    obj.cookie = (void*)1;
-    return writeObject(obj, true);
+    return writeFileDescriptor(dup(fd), true /*takeOwnership*/);
 }
 
 status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
@@ -764,7 +759,7 @@
             } else {
                 status = writeInt32(1);
                 if (!status) {
-                    status = writeFileDescriptor(fd);
+                    status = writeFileDescriptor(fd, true /*takeOwnership*/);
                     if (!status) {
                         outBlob->init(true /*mapped*/, ptr, len);
                         return NO_ERROR;
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 24ec4e8..75b07de 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -170,8 +170,11 @@
             patchCache.clear();
             dropShadowCache.clear();
             gradientCache.clear();
+            fontRenderer.clear();
             // fall through
         case kFlushMode_Moderate:
+            fontRenderer.flush();
+            textureCache.flush();
             pathCache.clear();
             roundRectShapeCache.clear();
             circleShapeCache.clear();
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index e8362dc..eb863e9 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -67,20 +67,63 @@
     const float whiteGamma = 1.0f / gamma;
 
     for (uint32_t i = 0; i <= 255; i++) {
-        mDefault[i] = i;
+        mGammaTable[i] = i;
 
         const float v = i / 255.0f;
         const float black = pow(v, blackGamma);
         const float white = pow(v, whiteGamma);
 
-        mBlackGamma[i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
-        mWhiteGamma[i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
+        mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
+        mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
     }
 
-    // Configure the font renderers
-    mDefaultRenderer.setGammaTable(&mDefault[0]);
-    mBlackGammaRenderer.setGammaTable(&mBlackGamma[0]);
-    mWhiteGammaRenderer.setGammaTable(&mWhiteGamma[0]);
+    memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount);
+    memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
+}
+
+GammaFontRenderer::~GammaFontRenderer() {
+    for (int i = 0; i < kGammaCount; i++) {
+        delete mRenderers[i];
+    }
+}
+
+void GammaFontRenderer::clear() {
+    for (int i = 0; i < kGammaCount; i++) {
+        delete mRenderers[i];
+        mRenderers[i] = NULL;
+    }
+}
+
+void GammaFontRenderer::flush() {
+    int count = 0;
+    int min = -1;
+    uint32_t minCount = UINT_MAX;
+
+    for (int i = 0; i < kGammaCount; i++) {
+        if (mRenderers[i]) {
+            count++;
+            if (mRenderersUsageCount[i] < minCount) {
+                minCount = mRenderersUsageCount[i];
+                min = i;
+            }
+        }
+    }
+
+    if (count <= 1 || min < 0) return;
+
+    delete mRenderers[min];
+    mRenderers[min] = NULL;
+}
+
+FontRenderer* GammaFontRenderer::getRenderer(Gamma gamma) {
+    FontRenderer* renderer = mRenderers[gamma];
+    if (!renderer) {
+        renderer = new FontRenderer();
+        mRenderers[gamma] = renderer;
+        renderer->setGammaTable(&mGammaTable[gamma * 256]);
+    }
+    mRenderersUsageCount[gamma]++;
+    return renderer;
 }
 
 FontRenderer& GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
@@ -92,12 +135,12 @@
         const int luminance = (r * 2 + g * 5 + b) >> 3;
 
         if (luminance <= mBlackThreshold) {
-            return mBlackGammaRenderer;
+            return *getRenderer(kGammaBlack);
         } else if (luminance >= mWhiteThreshold) {
-            return mWhiteGammaRenderer;
+            return *getRenderer(kGammaWhite);
         }
     }
-    return mDefaultRenderer;
+    return *getRenderer(kGammaDefault);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 96d960c..54c208e 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -26,36 +26,43 @@
 
 struct GammaFontRenderer {
     GammaFontRenderer();
+    ~GammaFontRenderer();
+
+    enum Gamma {
+        kGammaDefault = 0,
+        kGammaBlack = 1,
+        kGammaWhite = 2,
+        kGammaCount = 3
+    };
+
+    void clear();
+    void flush();
 
     FontRenderer& getFontRenderer(const SkPaint* paint);
 
     uint32_t getFontRendererCount() const {
-        return 3;
+        return kGammaCount;
     }
 
     uint32_t getFontRendererSize(uint32_t fontRenderer) const {
-        switch (fontRenderer) {
-            case 0:
-                return mDefaultRenderer.getCacheHeight() * mDefaultRenderer.getCacheWidth();
-            case 1:
-                return mBlackGammaRenderer.getCacheHeight() * mBlackGammaRenderer.getCacheWidth();
-            case 2:
-                return mWhiteGammaRenderer.getCacheHeight() * mWhiteGammaRenderer.getCacheWidth();
-        }
-        return 0;
+        if (fontRenderer >= kGammaCount) return 0;
+
+        FontRenderer* renderer = mRenderers[fontRenderer];
+        if (!renderer) return 0;
+
+        return renderer->getCacheHeight() * renderer->getCacheWidth();
     }
 
 private:
-    FontRenderer mDefaultRenderer;
-    FontRenderer mBlackGammaRenderer;
-    FontRenderer mWhiteGammaRenderer;
+    FontRenderer* getRenderer(Gamma gamma);
+
+    uint32_t mRenderersUsageCount[kGammaCount];
+    FontRenderer* mRenderers[kGammaCount];
 
     int mBlackThreshold;
     int mWhiteThreshold;
 
-    uint8_t mDefault[256];
-    uint8_t mBlackGamma[256];
-    uint8_t mWhiteGamma[256];
+    uint8_t mGammaTable[256 * kGammaCount];
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 5bd0d4f..8c01e3a 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -61,6 +61,9 @@
 #define PROPERTY_DROP_SHADOW_CACHE_SIZE "ro.hwui.drop_shadow_cache_size"
 #define PROPERTY_FBO_CACHE_SIZE "ro.hwui.fbo_cache_size"
 
+// These properties are defined in percentage (range 0..1)
+#define PROPERTY_TEXTURE_CACHE_FLUSH_RATE "ro.hwui.texture_cache_flush_rate"
+
 // These properties are defined in pixels
 #define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width"
 #define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height"
@@ -82,6 +85,8 @@
 #define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f
 #define DEFAULT_FBO_CACHE_SIZE 16
 
+#define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f
+
 #define DEFAULT_TEXT_GAMMA 1.4f
 #define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64
 #define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index fbdbf92..018ce3e 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -34,7 +34,8 @@
 
 TextureCache::TextureCache():
         mCache(GenerationCache<SkBitmap*, Texture*>::kUnlimitedCapacity),
-        mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)) {
+        mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
+        mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) {
     char property[PROPERTY_VALUE_MAX];
     if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) {
         INIT_LOGD("  Setting texture cache size to %sMB", property);
@@ -43,6 +44,15 @@
         INIT_LOGD("  Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE);
     }
 
+    if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, NULL) > 0) {
+        float flushRate = atof(property);
+        INIT_LOGD("  Setting texture cache flush rate to %.2f%%", flushRate * 100.0f);
+        setFlushRate(flushRate);
+    } else {
+        INIT_LOGD("  Using default texture cache flush rate of %.2f%%",
+                DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f);
+    }
+
     init();
 }
 
@@ -84,6 +94,10 @@
     }
 }
 
+void TextureCache::setFlushRate(float flushRate) {
+    mFlushRate = fmaxf(0.0f, fminf(1.0f, flushRate));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Callbacks
 ///////////////////////////////////////////////////////////////////////////////
@@ -168,6 +182,21 @@
     TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize);
 }
 
+void TextureCache::flush() {
+    if (mFlushRate >= 1.0f || mCache.size() == 0) return;
+    if (mFlushRate <= 0.0f) {
+        clear();
+        return;
+    }
+
+    uint32_t targetSize = uint32_t(mSize * mFlushRate);
+    TEXTURE_LOGD("TextureCache::flush: target size: %d", targetSize);
+
+    while (mSize > targetSize) {
+        mCache.removeOldest();
+    }
+}
+
 void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) {
     SkAutoLockPixels alp(*bitmap);
 
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index f7707f7..ce924b4 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -98,6 +98,17 @@
      */
     uint32_t getSize();
 
+    /**
+     * Partially flushes the cache. The amount of memory freed by a flush
+     * is defined by the flush rate.
+     */
+    void flush();
+    /**
+     * Indicates the percentage of the cache to retain when a
+     * memory trim is requested (see Caches::flush).
+     */
+    void setFlushRate(float flushRate);
+
 private:
     /**
      * Generates the texture from a bitmap into the specified texture structure.
@@ -119,6 +130,8 @@
     uint32_t mMaxSize;
     GLint mMaxTextureSize;
 
+    float mFlushRate;
+
     bool mDebugEnabled;
 
     Vector<SkBitmap*> mGarbage;
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index a862d00..590b4ae 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -154,7 +154,7 @@
 
         final Bitmap imageBitmap;
 
-        if (mHeight > maxResolution.second) {
+        if (mWidth > maxResolution.first || mHeight > maxResolution.second) {
             /**
              *  We need to scale the image
              */
@@ -971,14 +971,13 @@
             /**
              *  Create the bitmap from file
              */
-            if (nativeWidth / bitmapWidth > 1) {
-
-                final BitmapFactory.Options options = new BitmapFactory.Options();
-                options.inSampleSize = nativeWidth / (int)bitmapWidth;
-                srcBitmap = BitmapFactory.decodeFile(filename, options);
-            } else {
-                srcBitmap = BitmapFactory.decodeFile(filename);
-            }
+            int sampleSize = (int) Math.ceil(Math.max(
+                    (float) nativeWidth / bitmapWidth,
+                    (float) nativeHeight / bitmapHeight));
+            sampleSize = nextPowerOf2(sampleSize);
+            final BitmapFactory.Options options = new BitmapFactory.Options();
+            options.inSampleSize = sampleSize;
+            srcBitmap = BitmapFactory.decodeFile(filename, options);
         } else {
             bitmapWidth = width;
             bitmapHeight = height;
@@ -1009,4 +1008,14 @@
         srcBitmap.recycle();
         return bitmap;
     }
+
+    public static int nextPowerOf2(int n) {
+        n -= 1;
+        n |= n >>> 16;
+        n |= n >>> 8;
+        n |= n >>> 4;
+        n |= n >>> 2;
+        n |= n >>> 1;
+        return n + 1;
+    }
 }
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index b88296f..09152f5 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -56,6 +56,53 @@
     return OK;
 }
 
+// stolen from dalvik/vm/checkJni.cpp
+static bool isValidUtf8(const char* bytes) {
+    while (*bytes != '\0') {
+        unsigned char utf8 = *(bytes++);
+        // Switch on the high four bits.
+        switch (utf8 >> 4) {
+        case 0x00:
+        case 0x01:
+        case 0x02:
+        case 0x03:
+        case 0x04:
+        case 0x05:
+        case 0x06:
+        case 0x07:
+            // Bit pattern 0xxx. No need for any extra bytes.
+            break;
+        case 0x08:
+        case 0x09:
+        case 0x0a:
+        case 0x0b:
+        case 0x0f:
+            /*
+             * Bit pattern 10xx or 1111, which are illegal start bytes.
+             * Note: 1111 is valid for normal UTF-8, but not the
+             * modified UTF-8 used here.
+             */
+            return false;
+        case 0x0e:
+            // Bit pattern 1110, so there are two additional bytes.
+            utf8 = *(bytes++);
+            if ((utf8 & 0xc0) != 0x80) {
+                return false;
+            }
+            // Fall through to take care of the final byte.
+        case 0x0c:
+        case 0x0d:
+            // Bit pattern 110x, so there is one additional byte.
+            utf8 = *(bytes++);
+            if ((utf8 & 0xc0) != 0x80) {
+                return false;
+            }
+            break;
+        }
+    }
+    return true;
+}
+
 class MyMediaScannerClient : public MediaScannerClient
 {
 public:
@@ -123,7 +170,22 @@
             mEnv->ExceptionClear();
             return NO_MEMORY;
         }
-        if ((valueStr = mEnv->NewStringUTF(value)) == NULL) {
+        char *cleaned = NULL;
+        if (!isValidUtf8(value)) {
+            cleaned = strdup(value);
+            char *chp = cleaned;
+            char ch;
+            while ((ch = *chp)) {
+                if (ch & 0x80) {
+                    *chp = '?';
+                }
+                chp++;
+            }
+            value = cleaned;
+        }
+        valueStr = mEnv->NewStringUTF(value);
+        free(cleaned);
+        if (valueStr == NULL) {
             mEnv->DeleteLocalRef(nameStr);
             mEnv->ExceptionClear();
             return NO_MEMORY;
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index efa1c45..5a1e93a 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -49,6 +49,16 @@
         }\
     }
 
+
+static inline int16_t clamp16(int32_t sample)
+{
+    // check overflow for both positive and negative values:
+    // all bits above short range must me equal to sign bit
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
 // Namespaces
 namespace android {
 namespace {
@@ -707,13 +717,6 @@
 }   /* end LvmBundle_init */
 
 
-static inline int16_t clamp16(int32_t sample)
-{
-    if ((sample>>15) ^ (sample>>31))
-        sample = 0x7FFF ^ (sample>>31);
-    return sample;
-}
-
 //----------------------------------------------------------------------------
 // LvmBundle_process()
 //----------------------------------------------------------------------------
@@ -2459,6 +2462,9 @@
     LOGV("\tEffect_setEnabled() type %d, enabled %d", pContext->EffectType, enabled);
 
     if (enabled) {
+        // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due
+        // to their nature.
+        bool tempDisabled = false;
         switch (pContext->EffectType) {
             case LVM_BASS_BOOST:
                 if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
@@ -2471,6 +2477,7 @@
                 pContext->pBundledContext->SamplesToExitCountBb =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bBassEnabled = LVM_TRUE;
+                tempDisabled = pContext->pBundledContext->bBassTempDisabled;
                 break;
             case LVM_EQUALIZER:
                 if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
@@ -2495,6 +2502,7 @@
                 pContext->pBundledContext->SamplesToExitCountVirt =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
+                tempDisabled = pContext->pBundledContext->bVirtualizerTempDisabled;
                 break;
             case LVM_VOLUME:
                 if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE) {
@@ -2508,7 +2516,9 @@
                 LOGV("\tEffect_setEnabled() invalid effect type");
                 return -EINVAL;
         }
-        LvmEffect_enable(pContext);
+        if (!tempDisabled) {
+            LvmEffect_enable(pContext);
+        }
     } else {
         switch (pContext->EffectType) {
             case LVM_BASS_BOOST:
@@ -2683,12 +2693,19 @@
             LOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
             return lvmStatus;
         }
-    }else{
+    } else {
         //LOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
         //pContext->pBundledContext->NumberEffectsEnabled,
         //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
         // 2 is for stereo input
-        memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            for (size_t i=0; i < outBuffer->frameCount*2; i++){
+                outBuffer->s16[i] =
+                        clamp16((LVM_INT32)outBuffer->s16[i] + (LVM_INT32)inBuffer->s16[i]);
+            }
+        } else {
+            memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+        }
     }
 
     return status;
@@ -3047,9 +3064,10 @@
             LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE start");
             uint32_t device = *(uint32_t *)pCmdData;
 
-            if(pContext->EffectType == LVM_BASS_BOOST){
-                if((device == AUDIO_DEVICE_OUT_SPEAKER)||(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
-                   (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
+            if (pContext->EffectType == LVM_BASS_BOOST) {
+                if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
                           *(int32_t *)pCmdData);
                     LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");
@@ -3058,30 +3076,31 @@
                     // the effect must still report its original state as this can only be changed
                     // by the ENABLE/DISABLE command
 
-                    if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
+                    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
                         LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_BASS_BOOST %d",
                              *(int32_t *)pCmdData);
                         android::LvmEffect_disable(pContext);
-                        pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
                     }
-                }else{
+                    pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
+                } else {
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_BASS_BOOST %d",
                          *(int32_t *)pCmdData);
 
                     // If a device supports bassboost and the effect has been temporarily disabled
                     // previously then re-enable it
 
-                    if(pContext->pBundledContext->bBassTempDisabled == LVM_TRUE){
+                    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
                         LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_BASS_BOOST %d",
                              *(int32_t *)pCmdData);
                         android::LvmEffect_enable(pContext);
-                        pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
                     }
+                    pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
                 }
             }
-            if(pContext->EffectType == LVM_VIRTUALIZER){
-                if((device == AUDIO_DEVICE_OUT_SPEAKER)||(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
-                   (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
+            if (pContext->EffectType == LVM_VIRTUALIZER) {
+                if((device == AUDIO_DEVICE_OUT_SPEAKER)||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_VIRTUALIZER %d",
                           *(int32_t *)pCmdData);
                     LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_VIRTUALIZER");
@@ -3090,25 +3109,25 @@
                     // the effect must still report its original state as this can only be changed
                     // by the ENABLE/DISABLE command
 
-                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
+                    if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
                         LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_VIRTUALIZER %d",
                               *(int32_t *)pCmdData);
                         android::LvmEffect_disable(pContext);
-                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
                     }
-                }else{
+                    pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
+                } else {
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_VIRTUALIZER %d",
                           *(int32_t *)pCmdData);
 
                     // If a device supports virtualizer and the effect has been temporarily disabled
                     // previously then re-enable it
 
-                    if(pContext->pBundledContext->bVirtualizerTempDisabled == LVM_TRUE){
+                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
                         LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_VIRTUALIZER %d",
                               *(int32_t *)pCmdData);
                         android::LvmEffect_enable(pContext);
-                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
                     }
+                    pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
                 }
             }
             LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE end");
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/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/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 1ba79e5..e4de20a 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -257,6 +257,12 @@
             mForceRead = false;
             *timestampUs =
                 mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+
+            // Really make sure that this video recording frame will not be dropped.
+            if (*timestampUs < mStartTimeUs) {
+                LOGI("set timestampUs to start time stamp %lld us", mStartTimeUs);
+                *timestampUs = mStartTimeUs;
+            }
             return false;
         }
     }
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/Android.mk b/opengl/libs/Android.mk
index 3e66a13..5855b63 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -8,6 +8,7 @@
 
 LOCAL_SRC_FILES:= 	       \
 	EGL/egl_tls.cpp        \
+	EGL/egl_cache.cpp      \
 	EGL/egl_display.cpp    \
 	EGL/egl_object.cpp     \
 	EGL/egl.cpp 	       \
@@ -157,4 +158,3 @@
 include $(BUILD_SHARED_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1f9ce68..60ac34b 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -858,10 +858,17 @@
         return  NULL;
     }
 
+    // The EGL_ANDROID_blob_cache extension should not be exposed to
+    // applications.  It is used internally by the Android EGL layer.
+    if (!strcmp(procname, "eglSetBlobCacheFuncs")) {
+        return NULL;
+    }
+
     __eglMustCastToProperFunctionPointerType addr;
     addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
     if (addr) return addr;
 
+
     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
     pthread_mutex_lock(&sExtensionMapMutex);
 
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
new file mode 100644
index 0000000..aa40d58
--- /dev/null
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -0,0 +1,315 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "egl_cache.h"
+#include "egl_display.h"
+#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 {
+// ----------------------------------------------------------------------------
+
+#define BC_EXT_STR "EGL_ANDROID_blob_cache"
+
+//
+// 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 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() {
+    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) {
+            const char* exts = display->disp[i].queryString.extensions;
+            size_t bcExtLen = strlen(BC_EXT_STR);
+            size_t extsLen = strlen(exts);
+            bool equal = !strcmp(BC_EXT_STR, exts);
+            bool atStart = !strncmp(BC_EXT_STR " ", exts, bcExtLen+1);
+            bool atEnd = (bcExtLen+1) < extsLen &&
+                    !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
+            bool inMiddle = strstr(" " BC_EXT_STR " ", exts);
+            if (equal || atStart || atEnd || inMiddle) {
+                PFNEGLSETBLOBCACHEFUNCSPROC eglSetBlobCacheFuncs;
+                eglSetBlobCacheFuncs =
+                        reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSPROC>(
+                            cnx->egl.eglGetProcAddress("eglSetBlobCacheFuncs"));
+                if (eglSetBlobCacheFuncs == NULL) {
+                    LOGE("EGL_ANDROID_blob_cache advertised by display %d, "
+                            "but unable to get eglSetBlobCacheFuncs", i);
+                    continue;
+                }
+
+                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",
+                            err);
+                }
+            }
+        }
+    }
+    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);
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
new file mode 100644
index 0000000..05d5873
--- /dev/null
+++ b/opengl/libs/EGL/egl_cache.h
@@ -0,0 +1,123 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#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 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 83aafa6..558ca77 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -14,6 +14,7 @@
  ** limitations under the License.
  */
 
+#include "egl_cache.h"
 #include "egl_display.h"
 #include "egl_object.h"
 #include "egl_tls.h"
@@ -43,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) {
@@ -170,6 +172,8 @@
         }
     }
 
+    egl_cache_t::get()->initialize(this);
+
     EGLBoolean res = EGL_FALSE;
     for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
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..14104d1 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/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 64c54d9..eefb9fe 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -46,6 +46,16 @@
             </intent-filter>
         </receiver>
 
+        <!-- handle dock insertion, launch screensaver instead -->
+        <activity android:name=".DreamsDockLauncher"
+                android:label="@string/dreams_dock_launcher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.DESK_DOCK" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".usb.UsbStorageActivity"
                 android:excludeFromRecents="true">
         </activity>
diff --git a/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
index 9447e01..2509321 100644
--- a/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
Binary files differ
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/drawable-mdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
index 7f1aea1..be1cd31 100644
--- a/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
index e5cfc36..c096c7a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
index fecef3d..46f4c39 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
@@ -39,39 +39,39 @@
 
         <ImageView
             android:id="@+id/bluetooth"
-            android:layout_height="32dp"
-            android:layout_width="32dp"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
             android:scaleType="centerInside"
-            android:baseline="22dp"
+            android:baseline="18dp"
             android:visibility="gone"
             android:contentDescription="@null"
             />
 
         <FrameLayout
             android:id="@+id/netwerk"
-            android:layout_height="32dp"
-            android:layout_width="32dp"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
             android:layout_marginRight="4dp"
             >
 
             <ImageView
                 android:id="@+id/network_signal"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
                 android:contentDescription="@null"
                 />
 
             <ImageView
                 android:id="@+id/network_type"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
                 android:contentDescription="@null"
                 />
 
             <ImageView
                 android:id="@+id/network_direction"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
                 android:contentDescription="@null"
                 />
 
@@ -91,12 +91,14 @@
 
         <ImageView
             android:id="@+id/battery"
-            android:layout_height="32dp"
-            android:layout_width="32dp"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
             android:scaleType="centerInside"
             android:layout_toRightOf="@id/network_text"
             android:layout_alignBaseline="@id/network_signal"
-            android:baseline="22dp"
+            android:baseline="18dp"
+            android:layout_marginLeft="8dp"
+            android:layout_marginRight="8dp"
             android:contentDescription="@null"
             />
 
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-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 947ebb4..a8e7d0d 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -110,7 +110,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM-карта отсутствует."</string>
-    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Общий Bluetooth-модем."</string>
+    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-модем"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим полета."</string>
     <!-- String.format failed for translation -->
     <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
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 8108a90..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>
@@ -351,4 +356,7 @@
 
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
+
+    <!-- Description of the desk dock action that invokes the Android Dreams screen saver feature -->
+    <string name="dreams_dock_launcher">Activate screen saver</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
new file mode 100644
index 0000000..b8cdd73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DreamsDockLauncher.java
@@ -0,0 +1,39 @@
+package com.android.systemui;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Slog;
+
+public class DreamsDockLauncher extends Activity {
+    private static final String TAG = "DreamsDockLauncher";
+    @Override
+    protected void onCreate (Bundle icicle) {
+        super.onCreate(icicle);
+        try {
+            String component = Settings.Secure.getString(
+                    getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+            if (component != null) {
+                ComponentName cn = ComponentName.unflattenFromString(component);
+                Intent zzz = new Intent(Intent.ACTION_MAIN)
+                    .setComponent(cn)
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                        | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+                        );
+                startActivity(zzz);
+            } else {
+                Slog.e(TAG, "Couldn't start screen saver: none selected");
+            }
+        } catch (android.content.ActivityNotFoundException exc) {
+            // no screensaver? give up
+            Slog.e(TAG, "Couldn't start screen saver: none installed");
+        }
+        finish();
+    }
+}
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/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/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 3ad716b..06cd69e 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -35,15 +35,18 @@
 import android.text.TextWatcher;
 import android.text.method.DigitsKeyListener;
 import android.text.method.TextKeyListener;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup.LayoutParams;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.EditText;
 import android.widget.LinearLayout;
+import android.widget.Space;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
@@ -114,6 +117,7 @@
                 Settings.Secure.getInt(mContext.getContentResolver(),
                         Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, 0)
                         != 0);
+        boolean imeOrDeleteButtonVisible = false;
         if (mIsAlpha) {
             // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
             mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
@@ -129,6 +133,7 @@
             View pinDelete = findViewById(R.id.pinDel);
             if (pinDelete != null) {
                 pinDelete.setVisibility(View.VISIBLE);
+                imeOrDeleteButtonVisible = true;
                 pinDelete.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
@@ -181,6 +186,7 @@
                 Context.INPUT_METHOD_SERVICE);
         if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
             switchImeButton.setVisibility(View.VISIBLE);
+            imeOrDeleteButtonVisible = true;
             switchImeButton.setOnClickListener(new OnClickListener() {
                 public void onClick(View v) {
                     mCallback.pokeWakelock(); // Leave the screen on a bit longer
@@ -188,6 +194,16 @@
                 }
             });
         }
+
+        // If no icon is visible, reset the left margin on the password field so the text is
+        // still centered.
+        if (!imeOrDeleteButtonVisible) {
+            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+            if (params instanceof MarginLayoutParams) {
+                ((MarginLayoutParams)params).leftMargin = 0;
+                mPasswordEntry.setLayoutParams(params);
+            }
+        }
     }
 
     /**
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/preloaded-classes b/preloaded-classes
index 31d49ce..c29ba15 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -18,7 +18,12 @@
 android.accounts.IAccountManagerResponse$Stub
 android.animation.Animator
 android.animation.Animator$AnimatorListener
+android.animation.AnimatorInflater
 android.animation.AnimatorListenerAdapter
+android.animation.AnimatorSet
+android.animation.AnimatorSet$AnimatorSetListener
+android.animation.AnimatorSet$Builder
+android.animation.AnimatorSet$Node
 android.animation.FloatEvaluator
 android.animation.FloatKeyframeSet
 android.animation.IntEvaluator
@@ -57,6 +62,7 @@
 android.app.ActivityThread$GcIdler
 android.app.ActivityThread$H
 android.app.ActivityThread$Idler
+android.app.ActivityThread$Profiler
 android.app.ActivityThread$ProviderClientRecord
 android.app.ActivityThread$ProviderRefCount
 android.app.ActivityThread$ReceiverData
@@ -71,6 +77,8 @@
 android.app.ApplicationPackageManager
 android.app.ApplicationPackageManager$ResourceName
 android.app.ApplicationThreadNative
+android.app.BackStackRecord
+android.app.BackStackRecord$Op
 android.app.ContextImpl
 android.app.ContextImpl$1
 android.app.ContextImpl$10
@@ -111,9 +119,15 @@
 android.app.Dialog
 android.app.Dialog$1
 android.app.Dialog$ListenersHandler
+android.app.DialogFragment
+android.app.Fragment
 android.app.FragmentManager
+android.app.FragmentManager$BackStackEntry
 android.app.FragmentManagerImpl
 android.app.FragmentManagerImpl$1
+android.app.FragmentManagerImpl$2
+android.app.FragmentManagerImpl$3
+android.app.FragmentTransaction
 android.app.IActivityManager
 android.app.IActivityManager$ContentProviderHolder
 android.app.IActivityManager$ContentProviderHolder$1
@@ -134,6 +148,10 @@
 android.app.IntentReceiverLeaked
 android.app.IntentService
 android.app.IntentService$ServiceHandler
+android.app.ListActivity
+android.app.ListActivity$1
+android.app.ListActivity$2
+android.app.ListFragment
 android.app.LoadedApk
 android.app.LoadedApk$ReceiverDispatcher
 android.app.LoadedApk$ReceiverDispatcher$Args
@@ -328,6 +346,7 @@
 android.graphics.AvoidXfermode
 android.graphics.Bitmap
 android.graphics.Bitmap$1
+android.graphics.Bitmap$2
 android.graphics.Bitmap$BitmapFinalizer
 android.graphics.Bitmap$Config
 android.graphics.BitmapFactory
@@ -719,6 +738,7 @@
 android.text.style.MetricAffectingSpan
 android.text.style.ParagraphStyle
 android.text.style.ReplacementSpan
+android.text.style.SpellCheckSpan
 android.text.style.StyleSpan
 android.text.style.SuggestionSpan
 android.text.style.UpdateAppearance
@@ -870,6 +890,7 @@
 android.view.View$OnTouchListener
 android.view.View$PerformClick
 android.view.View$ScrollabilityCache
+android.view.View$TransformationInfo
 android.view.View$UnsetPressedState
 android.view.ViewConfiguration
 android.view.ViewGroup
@@ -934,6 +955,7 @@
 android.view.inputmethod.ExtractedText
 android.view.inputmethod.ExtractedText$1
 android.view.inputmethod.InputConnection
+android.view.inputmethod.InputConnectionWrapper
 android.view.inputmethod.InputMethodManager
 android.view.inputmethod.InputMethodManager$1
 android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
@@ -946,12 +968,16 @@
 android.widget.AbsListView
 android.widget.AbsListView$1
 android.widget.AbsListView$2
+android.widget.AbsListView$3
 android.widget.AbsListView$AdapterDataSetObserver
 android.widget.AbsListView$CheckForTap
+android.widget.AbsListView$FlingRunnable
+android.widget.AbsListView$FlingRunnable$1
 android.widget.AbsListView$LayoutParams
 android.widget.AbsListView$OnScrollListener
 android.widget.AbsListView$PerformClick
 android.widget.AbsListView$RecycleBin
+android.widget.AbsListView$RecyclerListener
 android.widget.AbsListView$SavedState
 android.widget.AbsListView$SavedState$1
 android.widget.AbsListView$SelectionBoundsAdjuster
@@ -975,13 +1001,19 @@
 android.widget.Checkable
 android.widget.CheckedTextView
 android.widget.CompoundButton
+android.widget.CompoundButton$OnCheckedChangeListener
 android.widget.CursorAdapter
 android.widget.CursorFilter$CursorFilterClient
+android.widget.EdgeEffect
 android.widget.EdgeGlow
 android.widget.EditText
 android.widget.ExpandableListView
+android.widget.FastScroller
+android.widget.FastScroller$1
+android.widget.FastScroller$ScrollFade
 android.widget.Filter
 android.widget.Filter$FilterListener
+android.widget.Filter$FilterResults
 android.widget.Filter$ResultsHandler
 android.widget.Filterable
 android.widget.FrameLayout
@@ -1030,17 +1062,30 @@
 android.widget.Spinner
 android.widget.SpinnerAdapter
 android.widget.StackView
+android.widget.Switch
 android.widget.TabHost
+android.widget.TabHost$ContentStrategy
+android.widget.TabHost$FactoryContentStrategy
+android.widget.TabHost$IndicatorStrategy
+android.widget.TabHost$LabelAndIconIndicatorStrategy
+android.widget.TabHost$OnTabChangeListener
+android.widget.TabHost$TabContentFactory
+android.widget.TabHost$TabSpec
+android.widget.TabHost$ViewIndicatorStrategy
 android.widget.TabWidget
+android.widget.TabWidget$OnTabSelectionChanged
+android.widget.TabWidget$TabClickListener
 android.widget.TableLayout
 android.widget.TableRow
 android.widget.TextView
+android.widget.TextView$2
 android.widget.TextView$3
 android.widget.TextView$Blink
 android.widget.TextView$BufferType
 android.widget.TextView$ChangeWatcher
 android.widget.TextView$CharWrapper
 android.widget.TextView$Drawables
+android.widget.TextView$EasyEditSpanController
 android.widget.TextView$InputContentType
 android.widget.TextView$InputMethodState
 android.widget.TextView$OnEditorActionListener
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 69560e5..96e8eb9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2066,7 +2066,16 @@
         // The first time a track is added we wait
         // for all its buffers to be filled before processing it
         mAudioMixer->setActiveTrack(track->name());
-        if (cblk->framesReady() && track->isReady() &&
+        // make sure that we have enough frames to mix one full buffer
+        uint32_t minFrames = 1;
+        if (!track->isStopped() && !track->isPausing()) {
+            if (t->sampleRate() == (int)mSampleRate) {
+                minFrames = mFrameCount;
+            } else {
+                minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1;
+            }
+        }
+        if ((cblk->framesReady() >= minFrames) && track->isReady() &&
                 !track->isPaused() && !track->isTerminated())
         {
             //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 851cb33..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;
@@ -171,6 +178,12 @@
     private static final int ENABLED  = 1;
     private static final int DISABLED = 0;
 
+    private static final boolean ADD = true;
+    private static final boolean REMOVE = false;
+
+    private static final boolean TO_DEFAULT_TABLE = true;
+    private static final boolean TO_SECONDARY_TABLE = false;
+
     // Share the event space with NetworkStateTracker (which can't see this
     // internal class but sends us events).  If you change these, change
     // NetworkStateTracker.java too.
@@ -485,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);
@@ -501,7 +520,7 @@
         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
         INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
 
-        mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper());
+        mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper());
         mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
                                   mTethering.getTetherableWifiRegexs().length != 0 ||
                                   mTethering.getTetherableBluetoothRegexs().length != 0) &&
@@ -525,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
@@ -1146,23 +1239,24 @@
         return false;
     }
 
-    private boolean addRoute(LinkProperties p, RouteInfo r) {
-        return modifyRoute(p.getInterfaceName(), p, r, 0, true);
+    private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
+        return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable);
     }
 
-    private boolean removeRoute(LinkProperties p, RouteInfo r) {
-        return modifyRoute(p.getInterfaceName(), p, r, 0, false);
+    private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
+        return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable);
     }
 
     private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
-        return modifyRouteToAddress(lp, addr, true);
+        return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE);
     }
 
     private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
-        return modifyRouteToAddress(lp, addr, false);
+        return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE);
     }
 
-    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) {
+    private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
+            boolean toDefaultTable) {
         RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
         if (bestRoute == null) {
             bestRoute = RouteInfo.makeHostRoute(addr);
@@ -1176,15 +1270,15 @@
                 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
             }
         }
-        return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd);
+        return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable);
     }
 
     private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
-            boolean doAdd) {
+            boolean doAdd, boolean toDefaultTable) {
         if ((ifaceName == null) || (lp == null) || (r == null)) return false;
 
         if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
-            loge("Error adding route - too much recursion");
+            loge("Error modifying route - too much recursion");
             return false;
         }
 
@@ -1199,14 +1293,18 @@
                     // route to it's gateway
                     bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
                 }
-                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd);
+                modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
             }
         }
         if (doAdd) {
             if (VDBG) log("Adding " + r + " for interface " + ifaceName);
-            mAddedRoutes.add(r);
             try {
-                mNetd.addRoute(ifaceName, r);
+                if (toDefaultTable) {
+                    mAddedRoutes.add(r);  // only track default table - only one apps can effect
+                    mNetd.addRoute(ifaceName, r);
+                } else {
+                    mNetd.addSecondaryRoute(ifaceName, r);
+                }
             } catch (Exception e) {
                 // never crash - catch them all
                 if (VDBG) loge("Exception trying to add a route: " + e);
@@ -1215,18 +1313,29 @@
         } else {
             // if we remove this one and there are no more like it, then refcount==0 and
             // we can remove it from the table
-            mAddedRoutes.remove(r);
-            if (mAddedRoutes.contains(r) == false) {
+            if (toDefaultTable) {
+                mAddedRoutes.remove(r);
+                if (mAddedRoutes.contains(r) == false) {
+                    if (VDBG) log("Removing " + r + " for interface " + ifaceName);
+                    try {
+                        mNetd.removeRoute(ifaceName, r);
+                    } catch (Exception e) {
+                        // never crash - catch them all
+                        if (VDBG) loge("Exception trying to remove a route: " + e);
+                        return false;
+                    }
+                } else {
+                    if (VDBG) log("not removing " + r + " as it's still in use");
+                }
+            } else {
                 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
                 try {
-                    mNetd.removeRoute(ifaceName, r);
+                    mNetd.removeSecondaryRoute(ifaceName, r);
                 } catch (Exception e) {
                     // never crash - catch them all
                     if (VDBG) loge("Exception trying to remove a route: " + e);
                     return false;
                 }
-            } else {
-                if (VDBG) log("not removing " + r + " as it's still in use");
             }
         }
         return true;
@@ -1862,14 +1971,21 @@
 
         for (RouteInfo r : routeDiff.removed) {
             if (isLinkDefault || ! r.isDefaultRoute()) {
-                removeRoute(curLp, r);
+                removeRoute(curLp, r, TO_DEFAULT_TABLE);
+            }
+            if (isLinkDefault == false) {
+                // remove from a secondary route table
+                removeRoute(curLp, r, TO_SECONDARY_TABLE);
             }
         }
 
         for (RouteInfo r :  routeDiff.added) {
             if (isLinkDefault || ! r.isDefaultRoute()) {
-                addRoute(newLp, r);
+                addRoute(newLp, r, TO_DEFAULT_TABLE);
             } else {
+                // add to a secondary route table
+                addRoute(newLp, r, TO_SECONDARY_TABLE);
+
                 // many radios add a default route even when we don't want one.
                 // remove the default route unless somebody else has asked for it
                 String ifaceName = newLp.getInterfaceName();
@@ -2450,12 +2566,6 @@
         int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
         boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
-        // Short term disabling of Tethering if DUN is required.
-        // TODO - fix multi-connection tethering using policy-base routing
-        int[] upstreamConnTypes = mTethering.getUpstreamIfaceTypes();
-        for (int i : upstreamConnTypes) {
-            if (i == ConnectivityManager.TYPE_MOBILE_DUN) return false;
-        }
         return tetherEnabledInSettings && mTetheringConfigValid;
     }
 
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 4e4fe4a..da960ae 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -59,7 +59,11 @@
 import java.io.PrintWriter;
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
@@ -77,6 +81,9 @@
     private static final int ADD = 1;
     private static final int REMOVE = 2;
 
+    private static final String DEFAULT = "default";
+    private static final String SECONDARY = "secondary";
+
     /**
      * Name representing {@link #setGlobalAlert(long)} limit when delivered to
      * {@link INetworkManagementEventObserver#limitReached(String, String)}.
@@ -505,15 +512,25 @@
 
     public void addRoute(String interfaceName, RouteInfo route) {
         mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
-        modifyRoute(interfaceName, ADD, route);
+        modifyRoute(interfaceName, ADD, route, DEFAULT);
     }
 
     public void removeRoute(String interfaceName, RouteInfo route) {
         mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
-        modifyRoute(interfaceName, REMOVE, route);
+        modifyRoute(interfaceName, REMOVE, route, DEFAULT);
     }
 
-    private void modifyRoute(String interfaceName, int action, RouteInfo route) {
+    public void addSecondaryRoute(String interfaceName, RouteInfo route) {
+        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
+        modifyRoute(interfaceName, ADD, route, SECONDARY);
+    }
+
+    public void removeSecondaryRoute(String interfaceName, RouteInfo route) {
+        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
+        modifyRoute(interfaceName, REMOVE, route, SECONDARY);
+    }
+
+    private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) {
         ArrayList<String> rsp;
 
         StringBuilder cmd;
@@ -521,12 +538,12 @@
         switch (action) {
             case ADD:
             {
-                cmd = new StringBuilder("interface route add " + interfaceName);
+                cmd = new StringBuilder("interface route add " + interfaceName + " " + type);
                 break;
             }
             case REMOVE:
             {
-                cmd = new StringBuilder("interface route remove " + interfaceName);
+                cmd = new StringBuilder("interface route remove " + interfaceName + " " + type);
                 break;
             }
             default:
@@ -833,14 +850,33 @@
         }
     }
 
+    private void modifyNat(String cmd, String internalInterface, String externalInterface)
+            throws SocketException {
+        cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface);
+
+        NetworkInterface internalNetworkInterface =
+                NetworkInterface.getByName(internalInterface);
+        Collection<InterfaceAddress>interfaceAddresses =
+                internalNetworkInterface.getInterfaceAddresses();
+        cmd += " " + interfaceAddresses.size();
+        for (InterfaceAddress ia : interfaceAddresses) {
+            InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(),
+                    ia.getNetworkPrefixLength());
+            cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength();
+        }
+
+        mConnector.doCommand(cmd);
+    }
+
     public void enableNat(String internalInterface, String externalInterface)
             throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")");
         try {
-            mConnector.doCommand(
-                    String.format("nat enable %s %s", internalInterface, externalInterface));
-        } catch (NativeDaemonConnectorException e) {
+            modifyNat("enable", internalInterface, externalInterface);
+        } catch (Exception e) {
+            Log.e(TAG, "enableNat got Exception " + e.toString());
             throw new IllegalStateException(
                     "Unable to communicate to native daemon for enabling NAT interface");
         }
@@ -850,10 +886,11 @@
             throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")");
         try {
-            mConnector.doCommand(
-                    String.format("nat disable %s %s", internalInterface, externalInterface));
-        } catch (NativeDaemonConnectorException e) {
+            modifyNat("disable", internalInterface, externalInterface);
+        } catch (Exception e) {
+            Log.e(TAG, "disableNat got Exception " + e.toString());
             throw new IllegalStateException(
                     "Unable to communicate to native daemon for disabling NAT interface");
         }
@@ -1099,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/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 431cc39..280b329 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -123,6 +123,10 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (getResultCode() != Activity.RESULT_OK) {
+                if (LOG) {
+                    Slog.v(TAG, "Handling broadcast result for action " + intent.getAction() 
+                            + ": canceled: " + getResultCode());
+                }
                 return;
             }
 
@@ -151,6 +155,12 @@
                         category = Intent.CATEGORY_HOME;
                     }
                 }
+
+                if (LOG) {
+                    Slog.v(TAG, String.format(
+                        "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s", 
+                        intent.getAction(), enableFlags, disableFlags, category));
+                }
                 
                 if (category != null) {
                     // This is the new activity that will serve as home while
@@ -424,11 +434,22 @@
         }
     }
 
+    final static boolean isDeskDockState(int state) {
+        switch (state) {
+            case Intent.EXTRA_DOCK_STATE_DESK:
+            case Intent.EXTRA_DOCK_STATE_LE_DESK:
+            case Intent.EXTRA_DOCK_STATE_HE_DESK:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     final void updateConfigurationLocked(boolean sendIt) {
         int uiMode = Configuration.UI_MODE_TYPE_NORMAL;
         if (mCarModeEnabled) {
             uiMode = Configuration.UI_MODE_TYPE_CAR;
-        } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+        } else if (isDeskDockState(mDockState)) {
             uiMode = Configuration.UI_MODE_TYPE_DESK;
         }
         if (mCarModeEnabled) {
@@ -477,7 +498,7 @@
             if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
                 adjustStatusBarCarModeLocked();
                 oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
-            } else if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_DESK) {
+            } else if (isDeskDockState(mLastBroadcastState)) {
                 oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
             }
 
@@ -491,12 +512,12 @@
                     mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
                     action = UiModeManager.ACTION_ENTER_CAR_MODE;
                 }
-            } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
-                if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_DESK) {
+            } else if (isDeskDockState(mDockState)) {
+                if (!isDeskDockState(mLastBroadcastState)) {
                     if (oldAction != null) {
                         mContext.sendBroadcast(new Intent(oldAction));
                     }
-                    mLastBroadcastState = Intent.EXTRA_DOCK_STATE_DESK;
+                    mLastBroadcastState = mDockState;
                     action = UiModeManager.ACTION_ENTER_DESK_MODE;
                 }
             } else {
@@ -505,6 +526,12 @@
             }
 
             if (action != null) {
+                if (LOG) {
+                    Slog.v(TAG, String.format(
+                        "updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
+                        action, enableFlags, disableFlags));
+                }
+
                 // Send the ordered broadcast; the result receiver will receive after all
                 // broadcasts have been sent. If any broadcast receiver changes the result
                 // code from the initial value of RESULT_OK, then the result receiver will
@@ -526,7 +553,7 @@
                     if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
                         homeIntent = buildHomeIntent(Intent.CATEGORY_CAR_DOCK);
                     }
-                } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+                } else if (isDeskDockState(mDockState)) {
                     if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
                         homeIntent = buildHomeIntent(Intent.CATEGORY_DESK_DOCK);
                     }
@@ -535,6 +562,12 @@
                         homeIntent = buildHomeIntent(Intent.CATEGORY_HOME);
                     }
                 }
+
+                if (LOG) {
+                    Slog.v(TAG, "updateLocked: null action, mDockState="
+                            + mDockState +", firing homeIntent: " + homeIntent);
+                }
+
                 if (homeIntent != null) {
                     try {
                         mContext.startActivity(homeIntent);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5bfe6f8..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();
     }
 
     /**
@@ -921,18 +916,14 @@
                     Slog.d(TAG, "ACTION_SCREEN_ON");
                 }
                 mAlarmManager.cancel(mIdleIntent);
-                mDeviceIdle = false;
                 mScreenOff = false;
-                // Once the screen is on, we are not keeping WIFI running
-                // because of any locks so clear that tracking immediately.
-                reportStartWorkSource();
                 evaluateTrafficStatsPolling();
                 mWifiStateMachine.enableRssiPolling(true);
                 if (mBackgroundScanSupported) {
                     mWifiStateMachine.enableBackgroundScanCommand(false);
                 }
                 mWifiStateMachine.enableAllNetworks();
-                updateWifiState();
+                setDeviceIdleAndUpdateWifi(false);
             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                 if (DBG) {
                     Slog.d(TAG, "ACTION_SCREEN_OFF");
@@ -950,36 +941,17 @@
                  * or plugged in to AC).
                  */
                 if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) {
-                    WifiInfo info = mWifiStateMachine.syncRequestConnectionInfo();
-                    if (info.getSupplicantState() != SupplicantState.COMPLETED) {
-                        // we used to go to sleep immediately, but this caused some race conditions
-                        // we don't have time to track down for this release.  Delay instead,
-                        // but not as long as we would if connected (below)
-                        // TODO - fix the race conditions and switch back to the immediate turn-off
-                        long triggerTime = System.currentTimeMillis() + (2*60*1000); // 2 min
-                        if (DBG) {
-                            Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for 120,000 ms");
-                        }
-                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
-                        //  // do not keep Wifi awake when screen is off if Wifi is not associated
-                        //  mDeviceIdle = true;
-                        //  updateWifiState();
+                    //Delayed shutdown if wifi is connected
+                    if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
+                        if (DBG) Slog.d(TAG, "setting ACTION_DEVICE_IDLE: " + idleMillis + " ms");
+                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+                                + idleMillis, mIdleIntent);
                     } else {
-                        long triggerTime = System.currentTimeMillis() + idleMillis;
-                        if (DBG) {
-                            Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis
-                                    + "ms");
-                        }
-                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+                        setDeviceIdleAndUpdateWifi(true);
                     }
                 }
             } else if (action.equals(ACTION_DEVICE_IDLE)) {
-                if (DBG) {
-                    Slog.d(TAG, "got ACTION_DEVICE_IDLE");
-                }
-                mDeviceIdle = true;
-                reportStartWorkSource();
-                updateWifiState();
+                setDeviceIdleAndUpdateWifi(true);
             } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                 /*
                  * Set a timer to put Wi-Fi to sleep, but only if the screen is off
@@ -1056,6 +1028,12 @@
         }
     };
 
+    private void setDeviceIdleAndUpdateWifi(boolean deviceIdle) {
+        mDeviceIdle = deviceIdle;
+        reportStartWorkSource();
+        updateWifiState();
+    }
+
     private synchronized void reportStartWorkSource() {
         mTmpWorkSource.clear();
         if (mDeviceIdle) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0c42926..05d42ada 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -120,6 +120,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -128,8 +129,10 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.lang.IllegalStateException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -857,9 +860,11 @@
     static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
     static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
     static final int DISPATCH_PROCESS_DIED = 32;
+    static final int REPORT_MEM_USAGE = 33;
 
     AlertDialog mUidAlert;
     CompatModeDialog mCompatModeDialog;
+    long mLastMemUsageReportTime = 0;
 
     final Handler mHandler = new Handler() {
         //public Handler() {
@@ -1199,6 +1204,71 @@
                 dispatchProcessDied(pid, uid);
                 break;
             }
+            case REPORT_MEM_USAGE: {
+                boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
+                if (!isDebuggable) {
+                    return;
+                }
+                synchronized (ActivityManagerService.this) {
+                    long now = SystemClock.uptimeMillis();
+                    if (now < (mLastMemUsageReportTime+10000)) {
+                        // Don't report more than every 10 seconds to somewhat
+                        // avoid spamming.
+                        return;
+                    }
+                    mLastMemUsageReportTime = now;
+                }
+                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", });
+                            final InputStreamReader converter = new InputStreamReader(
+                                    proc.getInputStream());
+                            BufferedReader in = new BufferedReader(converter);
+                            String line;
+                            while (true) {
+                                line = in.readLine();
+                                if (line == null) {
+                                    break;
+                                }
+                                if (line.length() > 0) {
+                                    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);
+                        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) {
+                                mLastMemUsageReportTime = now;
+                            }
+                        }
+                    }
+                };
+                thread.start();
+                break;
+            }
             }
         }
     };
@@ -1339,7 +1409,7 @@
                 return;
             }
 
-            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args);
+            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
         }
     }
 
@@ -2768,6 +2838,7 @@
                             addProcessToGcListLocked(rec);
                         }
                     }
+                    mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
                     scheduleAppGcsLocked();
                 }
             }
@@ -3136,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);
@@ -3308,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
@@ -3343,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;
     }
@@ -3374,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++) {
@@ -3462,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);
@@ -3481,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) {
@@ -6790,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");
                 }
             }
             
@@ -6986,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;
             }
@@ -9242,8 +9356,10 @@
     }
 
     final void dumpApplicationMemoryUsage(FileDescriptor fd,
-            PrintWriter pw, String prefix, String[] args) {
+            PrintWriter pw, String prefix, String[] args, boolean brief,
+            PrintWriter categoryPw) {
         boolean dumpAll = false;
+        boolean oomOnly = false;
         
         int opti = 0;
         while (opti < args.length) {
@@ -9254,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;
@@ -9382,15 +9501,20 @@
                 }
             }
 
-            pw.println();
-            pw.println("Total PSS by process:");
-            dumpMemItems(pw, "  ", procMems, true);
-            pw.println();
+            if (!brief && !oomOnly) {
+                pw.println();
+                pw.println("Total PSS by process:");
+                dumpMemItems(pw, "  ", procMems, true);
+                pw.println();
+            }
             pw.println("Total PSS by OOM adjustment:");
             dumpMemItems(pw, "  ", oomMems, false);
-            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/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 7bd29d9..423a78f 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -81,6 +81,9 @@
     private String[] mTetherableBluetoothRegexs;
     private Collection<Integer> mUpstreamIfaceTypes;
 
+    // used to synchronize public access to members
+    private Object mPublicSync;
+
     private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
     private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
     private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
@@ -91,6 +94,7 @@
 
     private final INetworkManagementService mNMService;
     private final INetworkStatsService mStatsService;
+    private final IConnectivityManager mConnService;
     private Looper mLooper;
     private HandlerThread mThread;
 
@@ -127,12 +131,15 @@
                                          // when RNDIS is enabled
 
     public Tethering(Context context, INetworkManagementService nmService,
-            INetworkStatsService statsService, Looper looper) {
+            INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
         mContext = context;
         mNMService = nmService;
         mStatsService = statsService;
+        mConnService = connService;
         mLooper = looper;
 
+        mPublicSync = new Object();
+
         mIfaces = new HashMap<String, TetherInterfaceSM>();
 
         // make our own thread so we don't anr the system
@@ -170,18 +177,25 @@
     }
 
     void updateConfiguration() {
-        mTetherableUsbRegexs = mContext.getResources().getStringArray(
+        String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_usb_regexs);
-        mTetherableWifiRegexs = mContext.getResources().getStringArray(
+        String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_wifi_regexs);
-        mTetherableBluetoothRegexs = mContext.getResources().getStringArray(
+        String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_bluetooth_regexs);
 
         int ifaceTypes[] = mContext.getResources().getIntArray(
                 com.android.internal.R.array.config_tether_upstream_types);
-        mUpstreamIfaceTypes = new ArrayList();
+        Collection<Integer> upstreamIfaceTypes = new ArrayList();
         for (int i : ifaceTypes) {
-            mUpstreamIfaceTypes.add(new Integer(i));
+            upstreamIfaceTypes.add(new Integer(i));
+        }
+
+        synchronized (mPublicSync) {
+            mTetherableUsbRegexs = tetherableUsbRegexs;
+            mTetherableWifiRegexs = tetherableWifiRegexs;
+            mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
+            mUpstreamIfaceTypes = upstreamIfaceTypes;
         }
 
         // check if the upstream type list needs to be modified due to secure-settings
@@ -192,17 +206,17 @@
         if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
         boolean found = false;
         boolean usb = false;
-        if (isWifi(iface)) {
-            found = true;
-        } else if (isUsb(iface)) {
-            found = true;
-            usb = true;
-        } else if (isBluetooth(iface)) {
-            found = true;
-        }
-        if (found == false) return;
+        synchronized (mPublicSync) {
+            if (isWifi(iface)) {
+                found = true;
+            } else if (isUsb(iface)) {
+                found = true;
+                usb = true;
+            } else if (isBluetooth(iface)) {
+                found = true;
+            }
+            if (found == false) return;
 
-        synchronized (mIfaces) {
             TetherInterfaceSM sm = mIfaces.get(iface);
             if (up) {
                 if (sm == null) {
@@ -229,46 +243,52 @@
     }
 
     private boolean isUsb(String iface) {
-        for (String regex : mTetherableUsbRegexs) {
-            if (iface.matches(regex)) return true;
+        synchronized (mPublicSync) {
+            for (String regex : mTetherableUsbRegexs) {
+                if (iface.matches(regex)) return true;
+            }
+            return false;
         }
-        return false;
     }
 
     public boolean isWifi(String iface) {
-        for (String regex : mTetherableWifiRegexs) {
-            if (iface.matches(regex)) return true;
+        synchronized (mPublicSync) {
+            for (String regex : mTetherableWifiRegexs) {
+                if (iface.matches(regex)) return true;
+            }
+            return false;
         }
-        return false;
     }
 
     public boolean isBluetooth(String iface) {
-        for (String regex : mTetherableBluetoothRegexs) {
-            if (iface.matches(regex)) return true;
+        synchronized (mPublicSync) {
+            for (String regex : mTetherableBluetoothRegexs) {
+                if (iface.matches(regex)) return true;
+            }
+            return false;
         }
-        return false;
     }
 
     public void interfaceAdded(String iface) {
         if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
         boolean found = false;
         boolean usb = false;
-        if (isWifi(iface)) {
-            found = true;
-        }
-        if (isUsb(iface)) {
-            found = true;
-            usb = true;
-        }
-        if (isBluetooth(iface)) {
-            found = true;
-        }
-        if (found == false) {
-            if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
-            return;
-        }
+        synchronized (mPublicSync) {
+            if (isWifi(iface)) {
+                found = true;
+            }
+            if (isUsb(iface)) {
+                found = true;
+                usb = true;
+            }
+            if (isBluetooth(iface)) {
+                found = true;
+            }
+            if (found == false) {
+                if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
+                return;
+            }
 
-        synchronized (mIfaces) {
             TetherInterfaceSM sm = mIfaces.get(iface);
             if (sm != null) {
                 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
@@ -283,7 +303,7 @@
 
     public void interfaceRemoved(String iface) {
         if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             TetherInterfaceSM sm = mIfaces.get(iface);
             if (sm == null) {
                 if (VDBG) {
@@ -301,7 +321,7 @@
     public int tether(String iface) {
         if (DBG) Log.d(TAG, "Tethering " + iface);
         TetherInterfaceSM sm = null;
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             sm = mIfaces.get(iface);
         }
         if (sm == null) {
@@ -319,7 +339,7 @@
     public int untether(String iface) {
         if (DBG) Log.d(TAG, "Untethering " + iface);
         TetherInterfaceSM sm = null;
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             sm = mIfaces.get(iface);
         }
         if (sm == null) {
@@ -336,21 +356,22 @@
 
     public int getLastTetherError(String iface) {
         TetherInterfaceSM sm = null;
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             sm = mIfaces.get(iface);
+            if (sm == null) {
+                Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
+                        ", ignoring");
+                return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
+            }
+            return sm.getLastError();
         }
-        if (sm == null) {
-            Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring");
-            return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
-        }
-        return sm.getLastError();
     }
 
+    // TODO - move all private methods used only by the state machine into the state machine
+    // to clarify what needs synchronized protection.
     private void sendTetherStateChangedBroadcast() {
-        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-        IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
         try {
-            if (!cm.isTetheringSupported()) return;
+            if (!mConnService.isTetheringSupported()) return;
         } catch (RemoteException e) {
             return;
         }
@@ -363,7 +384,7 @@
         boolean usbTethered = false;
         boolean bluetoothTethered = false;
 
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             Set ifaces = mIfaces.keySet();
             for (Object iface : ifaces) {
                 TetherInterfaceSM sm = mIfaces.get(iface);
@@ -469,7 +490,7 @@
         public void onReceive(Context content, Intent intent) {
             String action = intent.getAction();
             if (action.equals(UsbManager.ACTION_USB_STATE)) {
-                synchronized (Tethering.this) {
+                synchronized (Tethering.this.mPublicSync) {
                     boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
                     mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
                     // start tethering if we have a request pending
@@ -545,6 +566,7 @@
         return true;
     }
 
+    // TODO - return copies so people can't tamper
     public String[] getTetherableUsbRegexs() {
         return mTetherableUsbRegexs;
     }
@@ -561,7 +583,7 @@
         if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
         UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
 
-        synchronized (this) {
+        synchronized (mPublicSync) {
             if (enable) {
                 if (mRndisEnabled) {
                     tetherUsb(true);
@@ -581,11 +603,14 @@
     }
 
     public int[] getUpstreamIfaceTypes() {
-        updateConfiguration();
-        int values[] = new int[mUpstreamIfaceTypes.size()];
-        Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
-        for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
-            values[i] = iterator.next();
+        int values[];
+        synchronized (mPublicSync) {
+            updateConfiguration();
+            values = new int[mUpstreamIfaceTypes.size()];
+            Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
+            for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
+                values[i] = iterator.next();
+            }
         }
         return values;
     }
@@ -593,43 +618,46 @@
     public void checkDunRequired() {
         int secureSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.TETHER_DUN_REQUIRED, 2);
-        // 2 = not set, 0 = DUN not required, 1 = DUN required
-        if (secureSetting != 2) {
-            int requiredApn = (secureSetting == 1 ?
-                    ConnectivityManager.TYPE_MOBILE_DUN :
-                    ConnectivityManager.TYPE_MOBILE_HIPRI);
-            if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
-                while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
-                    mUpstreamIfaceTypes.remove(MOBILE_TYPE);
-                }
-                while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
-                    mUpstreamIfaceTypes.remove(HIPRI_TYPE);
-                }
-                if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
-                    mUpstreamIfaceTypes.add(DUN_TYPE);
-                }
-            } else {
-                while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
-                    mUpstreamIfaceTypes.remove(DUN_TYPE);
-                }
-                if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
-                    mUpstreamIfaceTypes.add(MOBILE_TYPE);
-                }
-                if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
-                    mUpstreamIfaceTypes.add(HIPRI_TYPE);
+        synchronized (mPublicSync) {
+            // 2 = not set, 0 = DUN not required, 1 = DUN required
+            if (secureSetting != 2) {
+                int requiredApn = (secureSetting == 1 ?
+                        ConnectivityManager.TYPE_MOBILE_DUN :
+                        ConnectivityManager.TYPE_MOBILE_HIPRI);
+                if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
+                    while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
+                        mUpstreamIfaceTypes.remove(MOBILE_TYPE);
+                    }
+                    while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
+                        mUpstreamIfaceTypes.remove(HIPRI_TYPE);
+                    }
+                    if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
+                        mUpstreamIfaceTypes.add(DUN_TYPE);
+                    }
+                } else {
+                    while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
+                        mUpstreamIfaceTypes.remove(DUN_TYPE);
+                    }
+                    if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
+                        mUpstreamIfaceTypes.add(MOBILE_TYPE);
+                    }
+                    if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
+                        mUpstreamIfaceTypes.add(HIPRI_TYPE);
+                    }
                 }
             }
-        }
-        if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
-            mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
-        } else {
-            mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
+                mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
+            } else {
+                mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            }
         }
     }
 
+    // TODO review API - maybe return ArrayList<String> here and below?
     public String[] getTetheredIfaces() {
         ArrayList<String> list = new ArrayList<String>();
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             Set keys = mIfaces.keySet();
             for (Object key : keys) {
                 TetherInterfaceSM sm = mIfaces.get(key);
@@ -647,7 +675,7 @@
 
     public String[] getTetheredIfacePairs() {
         final ArrayList<String> list = Lists.newArrayList();
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             for (TetherInterfaceSM sm : mIfaces.values()) {
                 if (sm.isTethered()) {
                     list.add(sm.mMyUpstreamIfaceName);
@@ -660,7 +688,7 @@
 
     public String[] getTetherableIfaces() {
         ArrayList<String> list = new ArrayList<String>();
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             Set keys = mIfaces.keySet();
             for (Object key : keys) {
                 TetherInterfaceSM sm = mIfaces.get(key);
@@ -678,7 +706,7 @@
 
     public String[] getErroredIfaces() {
         ArrayList<String> list = new ArrayList<String>();
-        synchronized (mIfaces) {
+        synchronized (mPublicSync) {
             Set keys = mIfaces.keySet();
             for (Object key : keys) {
                 TetherInterfaceSM sm = mIfaces.get(key);
@@ -777,43 +805,54 @@
             return res;
         }
 
-        public synchronized int getLastError() {
-            return mLastError;
+        public int getLastError() {
+            synchronized (Tethering.this.mPublicSync) {
+                return mLastError;
+            }
         }
 
-        private synchronized void setLastError(int error) {
-            mLastError = error;
+        private void setLastError(int error) {
+            synchronized (Tethering.this.mPublicSync) {
+                mLastError = error;
 
-            if (isErrored()) {
-                if (mUsb) {
-                    // note everything's been unwound by this point so nothing to do on
-                    // further error..
-                    Tethering.this.configureUsbIface(false);
+                if (isErrored()) {
+                    if (mUsb) {
+                        // note everything's been unwound by this point so nothing to do on
+                        // further error..
+                        Tethering.this.configureUsbIface(false);
+                    }
                 }
             }
         }
 
-        // synchronized between this getter and the following setter
-        public synchronized boolean isAvailable() {
-            return mAvailable;
+        public boolean isAvailable() {
+            synchronized (Tethering.this.mPublicSync) {
+                return mAvailable;
+            }
         }
 
-        private synchronized void setAvailable(boolean available) {
-            mAvailable = available;
+        private void setAvailable(boolean available) {
+            synchronized (Tethering.this.mPublicSync) {
+                mAvailable = available;
+            }
         }
 
-        // synchronized between this getter and the following setter
-        public synchronized boolean isTethered() {
-            return mTethered;
+        public boolean isTethered() {
+            synchronized (Tethering.this.mPublicSync) {
+                return mTethered;
+            }
         }
 
-        private synchronized void setTethered(boolean tethered) {
-            mTethered = tethered;
+        private void setTethered(boolean tethered) {
+            synchronized (Tethering.this.mPublicSync) {
+                mTethered = tethered;
+            }
         }
 
-        // synchronized between this getter and the following setter
-        public synchronized boolean isErrored() {
-            return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
+        public boolean isErrored() {
+            synchronized (Tethering.this.mPublicSync) {
+                return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
+            }
         }
 
         class InitialState extends State {
@@ -910,6 +949,7 @@
                 try {
                     mNMService.tetherInterface(mIfaceName);
                 } catch (Exception e) {
+                    Log.e(TAG, "Error Tethering: " + e.toString());
                     setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
 
                     transitionTo(mInitialState);
@@ -921,7 +961,7 @@
                 sendTetherStateChangedBroadcast();
             }
 
-            void cleanupUpstream() {
+            private void cleanupUpstream() {
                 if (mMyUpstreamIfaceName != null) {
                     // note that we don't care about errors here.
                     // sometimes interfaces are gone before we get
@@ -987,6 +1027,7 @@
                             try {
                                 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
                             } catch (Exception e) {
+                                Log.e(TAG, "Exception enabling Nat: " + e.toString());
                                 try {
                                     mNMService.untetherInterface(mIfaceName);
                                 } catch (Exception ee) {}
@@ -1150,13 +1191,11 @@
                 boolean retValue = true;
                 if (apnType == ConnectivityManager.TYPE_NONE) return false;
                 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
-                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                 int result = Phone.APN_REQUEST_FAILED;
                 String enableString = enableString(apnType);
                 if (enableString == null) return false;
                 try {
-                    result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+                    result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                             enableString, new Binder());
                 } catch (Exception e) {
                 }
@@ -1178,10 +1217,8 @@
             }
             protected boolean turnOffUpstreamMobileConnection() {
                 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
-                    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-                    IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                     try {
-                        cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+                        mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                                 enableString(mMobileApnReserved));
                     } catch (Exception e) {
                         return false;
@@ -1234,28 +1271,28 @@
             }
 
             protected void chooseUpstreamType(boolean tryCell) {
-                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
-                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                 int upType = ConnectivityManager.TYPE_NONE;
                 String iface = null;
 
                 updateConfiguration();
 
-                if (VDBG) {
-                    Log.d(TAG, "chooseUpstreamType has upstream iface types:");
-                    for (Integer netType : mUpstreamIfaceTypes) {
-                        Log.d(TAG, " " + netType);
+                synchronized (mPublicSync) {
+                    if (VDBG) {
+                        Log.d(TAG, "chooseUpstreamType has upstream iface types:");
+                        for (Integer netType : mUpstreamIfaceTypes) {
+                            Log.d(TAG, " " + netType);
+                        }
                     }
-                }
 
-                for (Integer netType : mUpstreamIfaceTypes) {
-                    NetworkInfo info = null;
-                    try {
-                        info = cm.getNetworkInfo(netType.intValue());
-                    } catch (RemoteException e) { }
-                    if ((info != null) && info.isConnected()) {
-                        upType = netType.intValue();
-                        break;
+                    for (Integer netType : mUpstreamIfaceTypes) {
+                        NetworkInfo info = null;
+                        try {
+                            info = mConnService.getNetworkInfo(netType.intValue());
+                        } catch (RemoteException e) { }
+                        if ((info != null) && info.isConnected()) {
+                            upType = netType.intValue();
+                            break;
+                        }
                     }
                 }
 
@@ -1283,7 +1320,7 @@
                 } else {
                     LinkProperties linkProperties = null;
                     try {
-                        linkProperties = cm.getLinkProperties(upType);
+                        linkProperties = mConnService.getLinkProperties(upType);
                     } catch (RemoteException e) { }
                     if (linkProperties != null) iface = linkProperties.getInterfaceName();
                 }
@@ -1483,14 +1520,14 @@
                     return;
         }
 
-        pw.println("mUpstreamIfaceTypes: ");
-        for (Integer netType : mUpstreamIfaceTypes) {
-            pw.println(" " + netType);
-        }
+        synchronized (mPublicSync) {
+            pw.println("mUpstreamIfaceTypes: ");
+            for (Integer netType : mUpstreamIfaceTypes) {
+                pw.println(" " + netType);
+            }
 
-        pw.println();
-        pw.println("Tether state:");
-        synchronized (mIfaces) {
+            pw.println();
+            pw.println("Tether state:");
             for (Object o : mIfaces.values()) {
                 pw.println(" "+o.toString());
             }
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/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 131f11c..8fc9a70 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -88,13 +88,14 @@
         try {
             try {
                 mSurface = new Surface(session, 0, "FreezeSurface",
-                        -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT);
+                        -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
                 if (mSurface == null || !mSurface.isValid()) {
                     // Screenshot failed, punt.
                     mSurface = null;
                     return;
                 }
                 mSurface.setLayer(FREEZE_LAYER + 1);
+                mSurface.show();
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate freeze surface", e);
             }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 2cd3062..8ed7966 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -8682,7 +8682,8 @@
         if (needRelayout) {
             requestAnimationLocked(0);
         } else if (animating) {
-            requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
+            final int refreshTimeUs = (int)(1000 / mDisplay.getRefreshRate());
+            requestAnimationLocked(currentTime + refreshTimeUs - SystemClock.uptimeMillis());
         }
 
         // Finally update all input windows now that the window changes have stabilized.
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 5b74fb8..c2c6b4d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -471,14 +471,21 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
+    SensorInterface* sensor = mSensorMap.valueFor(handle);
+    if (!sensor)
+        return BAD_VALUE;
+
     if (ns < 0)
         return BAD_VALUE;
 
+    nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
+    if (ns < minDelayNs) {
+        ns = minDelayNs;
+    }
+
     if (ns < MINIMUM_EVENTS_PERIOD)
         ns = MINIMUM_EVENTS_PERIOD;
 
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    if (!sensor) return BAD_VALUE;
     return sensor->setDelay(connection.get(), handle, ns);
 }
 
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 61a8358..b916bd7 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -30,6 +30,10 @@
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
 endif
 
+ifneq (,$(findstring $(TARGET_DEVICE),tuna toro maguro))
+	LOCAL_CFLAGS += -DREFRESH_RATE=48
+endif
+
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f4be168..329c052 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -141,6 +141,17 @@
     mDpiY = mNativeWindow->ydpi;
     mRefreshRate = fbDev->fps;
 
+
+/* FIXME: this is a temporary HACK until we are able to report the refresh rate
+ * properly from the HAL. The WindowManagerService now relies on this value.
+ */
+#ifndef REFRESH_RATE
+    mRefreshRate = fbDev->fps;
+#else
+    mRefreshRate = REFRESH_RATE;
+#warning "refresh rate set via makefile to REFRESH_RATE"
+#endif
+
     EGLint w, h, dummy;
     EGLint numConfigs=0;
     EGLSurface surface;
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index e30ccbf..68e6660 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -27,6 +27,7 @@
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
 
+
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -45,23 +46,64 @@
     }
 }
 
+status_t LayerScreenshot::captureLocked() {
+    GLfloat u, v;
+    status_t result = mFlinger->renderScreenToTextureLocked(0, &mTextureName, &u, &v);
+    if (result != NO_ERROR) {
+        return result;
+    }
+    initTexture(u, v);
+    return NO_ERROR;
+}
+
 status_t LayerScreenshot::capture() {
     GLfloat u, v;
     status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v);
     if (result != NO_ERROR) {
         return result;
     }
+    initTexture(u, v);
+    return NO_ERROR;
+}
 
+void LayerScreenshot::initTexture(GLfloat u, GLfloat v) {
     glBindTexture(GL_TEXTURE_2D, mTextureName);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
     mTexCoords[0] = 0;         mTexCoords[1] = v;
     mTexCoords[2] = 0;         mTexCoords[3] = 0;
     mTexCoords[4] = u;         mTexCoords[5] = 0;
     mTexCoords[6] = u;         mTexCoords[7] = v;
+}
 
-    return NO_ERROR;
+void LayerScreenshot::initStates(uint32_t w, uint32_t h, uint32_t flags) {
+    LayerBaseClient::initStates(w, h, flags);
+    if (!(flags & ISurfaceComposer::eHidden)) {
+        capture();
+    }
+}
+
+uint32_t LayerScreenshot::doTransaction(uint32_t flags)
+{
+    const Layer::State& draw(drawingState());
+    const Layer::State& curr(currentState());
+
+    if (draw.flags & ISurfaceComposer::eLayerHidden) {
+        if (!(curr.flags & ISurfaceComposer::eLayerHidden)) {
+            // we're going from hidden to visible
+            status_t err = captureLocked();
+            if (err != NO_ERROR) {
+                LOGW("createScreenshotSurface failed (%s)", strerror(-err));
+            }
+        }
+    } else if (curr.flags & ISurfaceComposer::eLayerHidden) {
+        // we're going from visible to hidden
+        if (mTextureName) {
+            glDeleteTextures(1, &mTextureName);
+            mTextureName = 0;
+        }
+    }
+    return LayerBaseClient::doTransaction(flags);
 }
 
 void LayerScreenshot::onDraw(const Region& clip) const
diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h
index e3a2b19..ab90047 100644
--- a/services/surfaceflinger/LayerScreenshot.h
+++ b/services/surfaceflinger/LayerScreenshot.h
@@ -41,12 +41,18 @@
 
         status_t capture();
 
+    virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
+    virtual uint32_t doTransaction(uint32_t flags);
     virtual void onDraw(const Region& clip) const;
     virtual bool isOpaque() const         { return false; }
     virtual bool isSecure() const         { return false; }
     virtual bool isProtectedByApp() const { return false; }
     virtual bool isProtectedByDRM() const { return false; }
     virtual const char* getTypeId() const { return "LayerScreenshot"; }
+
+private:
+    status_t captureLocked();
+    void initTexture(GLfloat u, GLfloat v);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a6d4147..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;
+            }
         }
     }
 }
@@ -1360,11 +1362,6 @@
         uint32_t w, uint32_t h, uint32_t flags)
 {
     sp<LayerScreenshot> layer = new LayerScreenshot(this, display, client);
-    status_t err = layer->capture();
-    if (err != NO_ERROR) {
-        layer.clear();
-        LOGW("createScreenshotSurface failed (%s)", strerror(-err));
-    }
     return layer;
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ea5bfa7..17028db 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -186,6 +186,8 @@
 
             status_t renderScreenToTexture(DisplayID dpy,
                     GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
+            status_t renderScreenToTextureLocked(DisplayID dpy,
+                    GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
 
             status_t postMessageAsync(const sp<MessageBase>& msg,
                     nsecs_t reltime=0, uint32_t flags = 0);
@@ -328,8 +330,6 @@
             status_t turnElectronBeamOnImplLocked(int32_t mode);
             status_t electronBeamOffAnimationImplLocked();
             status_t electronBeamOnAnimationImplLocked();
-            status_t renderScreenToTextureLocked(DisplayID dpy,
-                    GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
 
             void        debugFlashRegions();
             void        debugShowFPS() const;
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 171b371..3dd57ee 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -379,18 +379,19 @@
                 mode = AudioManager.MODE_RINGTONE;
                 break;
             case OFFHOOK:
-                Phone fgPhone = getFgPhone();
-                // While foreground call is in DIALING,
-                // ALERTING, ACTIVE and DISCONNECTING state
-                if (getActiveFgCallState() != Call.State.IDLE
-                        && getActiveFgCallState() != Call.State.DISCONNECTED) {
-                    if (fgPhone instanceof SipPhone) {
-                        // enable IN_COMMUNICATION audio mode for sipPhone
-                        mode = AudioManager.MODE_IN_COMMUNICATION;
-                    } else {
-                        // enable IN_CALL audio mode for telephony
-                        mode = AudioManager.MODE_IN_CALL;
-                    }
+                Phone offhookPhone = getFgPhone();
+                if (getActiveFgCallState() == Call.State.IDLE) {
+                    // There is no active Fg calls, the OFFHOOK state
+                    // is set by the Bg call. So set the phone to bgPhone.
+                    offhookPhone = getBgPhone();
+                }
+
+                if (offhookPhone instanceof SipPhone) {
+                    // enable IN_COMMUNICATION audio mode for sipPhone
+                    mode = AudioManager.MODE_IN_COMMUNICATION;
+                } else {
+                    // enable IN_CALL audio mode for telephony
+                    mode = AudioManager.MODE_IN_CALL;
                 }
                 break;
         }
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 97e7aa3..410e961 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -27,12 +27,14 @@
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
+import android.net.TrafficStats;
 import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
@@ -56,6 +58,7 @@
  */
 public abstract class DataConnectionTracker extends Handler {
     protected static final boolean DBG = true;
+    protected static final boolean VDBG = false;
 
     /**
      * IDLE: ready to start data connection setup, default state
@@ -114,8 +117,8 @@
     protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
     protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
     protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
-    protected static final int EVENT_START_NETSTAT_POLL = BASE + 17;
-    protected static final int EVENT_START_RECOVERY = BASE + 18;
+    protected static final int EVENT_DATA_STALL_ALARM = BASE + 17;
+    protected static final int EVENT_DO_RECOVERY = BASE + 18;
     protected static final int EVENT_APN_CHANGED = BASE + 19;
     protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
     protected static final int EVENT_NV_READY = BASE + 21;
@@ -164,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];
 
@@ -189,19 +194,16 @@
 
     /**
      * After detecting a potential connection problem, this is the max number
-     * of subsequent polls before attempting a radio reset.  At this point,
-     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
-     * poll for about 2 more minutes.
+     * of subsequent polls before attempting recovery.
      */
     protected static final int NO_RECV_POLL_LIMIT = 24;
-
     // 1 sec. default polling interval when screen is on.
     protected static final int POLL_NETSTAT_MILLIS = 1000;
     // 10 min. default polling interval when screen is off.
     protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
     // 2 min for round trip time
     protected static final int POLL_LONGEST_RTT = 120 * 1000;
-    // 10 for packets without ack
+    // Default sent packets without ack which triggers initial recovery steps
     protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
     // how long to wait before switching back to default APN
     protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
@@ -210,6 +212,13 @@
     // represents an invalid IP address
     protected static final String NULL_IP = "0.0.0.0";
 
+    // Default for the data stall alarm
+    protected static final int DATA_STALL_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 3;
+    // If attempt is less than this value we're doing first level recovery
+    protected static final int DATA_STALL_NO_RECV_POLL_LIMIT = 1;
+    // Tag for tracking stale alarms
+    protected static final String DATA_STALL_ALARM_TAG_EXTRA = "data.stall.alram.tag";
+
     // TODO: See if we can remove INTENT_RECONNECT_ALARM
     //       having to have different values for GSM and
     //       CDMA. If so we can then remove the need for
@@ -240,11 +249,19 @@
 
     protected long mTxPkts;
     protected long mRxPkts;
-    protected long mSentSinceLastRecv;
     protected int mNetStatPollPeriod;
-    protected int mNoRecvPollCount = 0;
     protected boolean mNetStatPollEnabled = false;
 
+    protected TxRxSum mDataStallTxRxSum = new TxRxSum(0, 0);
+    // Used to track stale data stall alarms.
+    protected int mDataStallAlarmTag = (int) SystemClock.elapsedRealtime();
+    // The current data stall alarm intent
+    protected PendingIntent mDataStallAlarmIntent = null;
+    // Number of packets sent since the last received packet
+    protected long mSentSinceLastRecv;
+    // Controls when a simple recovery attempt it to be tried
+    protected int mNoRecvPollCount = 0;
+
     // wifi connection status will be updated by sticky intent
     protected boolean mIsWifiConnected = false;
 
@@ -313,7 +330,8 @@
             } else if (action.startsWith(getActionIntentReconnectAlarm())) {
                 log("Reconnect alarm. Previous state was " + mState);
                 onActionIntentReconnectAlarm(intent);
-
+            } else if (action.equals(getActionIntentDataStallAlarm())) {
+                onActionIntentDataStallAlarm(intent);
             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 final android.net.NetworkInfo networkInfo = (NetworkInfo)
                         intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
@@ -363,6 +381,71 @@
         }
     }
 
+    /**
+     * Maintian the sum of transmit and receive packets.
+     *
+     * The packet counts are initizlied and reset to -1 and
+     * remain -1 until they can be updated.
+     */
+    public class TxRxSum {
+        public long txPkts;
+        public long rxPkts;
+
+        public TxRxSum() {
+            reset();
+        }
+
+        public TxRxSum(long txPkts, long rxPkts) {
+            this.txPkts = txPkts;
+            this.rxPkts = rxPkts;
+        }
+
+        public TxRxSum(TxRxSum sum) {
+            txPkts = sum.txPkts;
+            rxPkts = sum.rxPkts;
+        }
+
+        public void reset() {
+            txPkts = -1;
+            rxPkts = -1;
+        }
+
+        public String toString() {
+            return "{txSum=" + txPkts + " rxSum=" + rxPkts + "}";
+        }
+
+        public void updateTxRxSum() {
+            boolean txUpdated = false, rxUpdated = false;
+            long txSum = 0, rxSum = 0;
+            for (ApnContext apnContext : mApnContexts.values()) {
+                if (apnContext.getState() == State.CONNECTED) {
+                    DataConnectionAc dcac = apnContext.getDataConnectionAc();
+                    if (dcac == null) continue;
+
+                    LinkProperties linkProp = dcac.getLinkPropertiesSync();
+                    if (linkProp == null) continue;
+
+                    String iface = linkProp.getInterfaceName();
+
+                    if (iface != null) {
+                        long stats = TrafficStats.getTxPackets(iface);
+                        if (stats > 0) {
+                            txUpdated = true;
+                            txSum += stats;
+                        }
+                        stats = TrafficStats.getRxPackets(iface);
+                        if (stats > 0) {
+                            rxUpdated = true;
+                            rxSum += stats;
+                        }
+                    }
+                }
+            }
+            if (txUpdated) this.txPkts = txSum;
+            if (rxUpdated) this.rxPkts = rxSum;
+        }
+    }
+
     protected boolean isDataSetupCompleteOk(AsyncResult ar) {
         if (ar.exception != null) {
             if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
@@ -394,6 +477,13 @@
         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
     }
 
+    protected void onActionIntentDataStallAlarm(Intent intent) {
+        if (VDBG) log("onActionIntentDataStallAlarm: action=" + intent.getAction());
+        Message msg = obtainMessage(EVENT_DATA_STALL_ALARM, intent.getAction());
+        msg.arg1 = intent.getIntExtra(DATA_STALL_ALARM_TAG_EXTRA, 0);
+        sendMessage(msg);
+    }
+
     /**
      * Default constructor
      */
@@ -529,6 +619,7 @@
 
     // abstract methods
     protected abstract String getActionIntentReconnectAlarm();
+    protected abstract String getActionIntentDataStallAlarm();
     protected abstract void startNetStatPoll();
     protected abstract void stopNetStatPoll();
     protected abstract void restartRadio();
@@ -553,6 +644,10 @@
     protected abstract void onCleanUpAllConnections(String cause);
     protected abstract boolean isDataPossible(String apnType);
 
+    protected void onDataStallAlarm(int tag) {
+        loge("onDataStallAlarm: not impleted tag=" + tag);
+    }
+
     @Override
     public void handleMessage(Message msg) {
         switch (msg.what) {
@@ -575,6 +670,10 @@
                 onTrySetupData(reason);
                 break;
 
+            case EVENT_DATA_STALL_ALARM:
+                onDataStallAlarm(msg.arg1);
+                break;
+
             case EVENT_ROAMING_OFF:
                 if (getDataOnRoamingEnabled() == false) {
                     resetAllRetryCounts();
@@ -669,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);
@@ -1035,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/EventLogTags.logtags b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
index 9be7b80..427e5da 100644
--- a/telephony/java/com/android/internal/telephony/EventLogTags.logtags
+++ b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
@@ -56,3 +56,18 @@
 
 # Bad IP address
 50117 bad_ip_address (ip_address|3)
+
+# Data Stall Recovery mode DATA_STALL_RECOVERY_GET_DATA_CALL_LIST
+50118 data_stall_recovery_get_data_call_list (out_packet_count|1|1)
+
+# Data Stall Recovery mode DATA_STALL_RECOVERY_CLEANUP
+50119 data_stall_recovery_cleanup (out_packet_count|1|1)
+
+# Data Stall Recovery mode DATA_STALL_RECOVERY_REREGISTER
+50120 data_stall_recovery_reregister (out_packet_count|1|1)
+
+# Data Stall Recovery mode DATA_STALL_RECOVERY_RADIO_RESTART
+50121 data_stall_recovery_radio_restart (out_packet_count|1|1)
+
+# Data Stall Recovery mode DATA_STALL_RECOVERY_RADIO_RESTART_WITH_PROP
+50122 data_stall_recovery_radio_restart_with_prop (out_packet_count|1|1)
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index f5d05a1..5889372 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -69,6 +69,10 @@
     private static final String INTENT_RECONNECT_ALARM =
         "com.android.internal.telephony.cdma-reconnect";
 
+    private static final String INTENT_DATA_STALL_ALARM =
+        "com.android.internal.telephony.cdma-data-stall";
+
+
     /**
      * Constants for the data connection activity:
      * physical link down/up
@@ -149,6 +153,11 @@
     }
 
     @Override
+    protected String getActionIntentDataStallAlarm() {
+        return INTENT_DATA_STALL_ALARM;
+    }
+
+    @Override
     protected void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (mState != s) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index aa475e5..7cd01a1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -96,22 +96,37 @@
     private boolean mReregisterOnReconnectFailure = false;
     private ContentResolver mResolver;
 
-    // Count of PDP reset attempts; reset when we see incoming,
-    // call reRegisterNetwork, or pingTest succeeds.
-    private int mPdpResetCount = 0;
-
     // Recovery action taken in case of data stall
-    enum RecoveryAction {REREGISTER, RADIO_RESTART, RADIO_RESET};
-    private RecoveryAction mRecoveryAction = RecoveryAction.REREGISTER;
-
+    class RecoveryAction {
+        public static final int GET_DATA_CALL_LIST      = 0;
+        public static final int CLEANUP                 = 1;
+        public static final int REREGISTER              = 2;
+        public static final int RADIO_RESTART           = 3;
+        public static final int RADIO_RESTART_WITH_PROP = 4;
+    }
+    public int getRecoveryAction() {
+        int action = Settings.System.getInt(mPhone.getContext().getContentResolver(),
+                "radio.data.stall.recovery.action", RecoveryAction.GET_DATA_CALL_LIST);
+        if (VDBG) log("getRecoveryAction: " + action);
+        return action;
+    }
+    public void putRecoveryAction(int action) {
+        Settings.System.putInt(mPhone.getContext().getContentResolver(),
+                "radio.data.stall.recovery.action", action);
+        if (VDBG) log("putRecoveryAction: " + action);
+    }
 
     //***** Constants
 
     private static final int POLL_PDP_MILLIS = 5 * 1000;
 
-    private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
+    private static final String INTENT_RECONNECT_ALARM =
+        "com.android.internal.telephony.gprs-reconnect";
     private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "type";
 
+    private static final String INTENT_DATA_STALL_ALARM =
+        "com.android.internal.telephony.gprs-data-stall";
+
     static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
     static final String APN_ID = "apn_id";
     private boolean canSetPreferApn = false;
@@ -163,6 +178,11 @@
         p.getServiceStateTracker().registerForPsRestrictedDisabled(this,
                 EVENT_PS_RESTRICT_DISABLED, null);
 
+        // install reconnect intent filter for this data connection.
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_DATA_STALL_ALARM);
+        p.getContext().registerReceiver(mIntentReceiver, filter, null, p);
+
         mDataConnectionTracker = this;
         mResolver = mPhone.getContext().getContentResolver();
 
@@ -241,6 +261,11 @@
         return INTENT_RECONNECT_ALARM;
     }
 
+    @Override
+    protected String getActionIntentDataStallAlarm() {
+        return INTENT_DATA_STALL_ALARM;
+    }
+
     private ApnContext addApnContext(String type) {
         ApnContext apnContext = new ApnContext(type, LOG_TAG);
         apnContext.setDependencyMet(false);
@@ -524,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.
@@ -552,6 +577,7 @@
          */
         if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
         stopNetStatPoll();
+        stopDataStallAlarm();
         notifyDataConnection(Phone.REASON_DATA_DETACHED);
     }
 
@@ -560,6 +586,7 @@
         if (getOverallState() == State.CONNECTED) {
             if (DBG) log("onDataConnectionAttached: start polling notify attached");
             startNetStatPoll();
+            startDataStallAlarm();
             notifyDataConnection(Phone.REASON_DATA_ATTACHED);
         } else {
             // update APN availability so that APN can be enabled.
@@ -764,6 +791,8 @@
         }
 
         stopNetStatPoll();
+        stopDataStallAlarm();
+
         // TODO: Do we need mRequestedApnType?
         mRequestedApnType = Phone.APN_TYPE_DEFAULT;
     }
@@ -1236,6 +1265,7 @@
         // setState(State.CONNECTED);
         mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
         startNetStatPoll();
+        startDataStallAlarm();
         // reset reconnect timer
         apnContext.getDataConnection().resetRetryCount();
     }
@@ -1250,59 +1280,62 @@
     private void resetPollStats() {
         mTxPkts = -1;
         mRxPkts = -1;
-        mSentSinceLastRecv = 0;
         mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
-        mNoRecvPollCount = 0;
     }
 
     private void doRecovery() {
         if (getOverallState() == State.CONNECTED) {
-            int maxPdpReset = Settings.Secure.getInt(mResolver,
-                    Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
-                    DEFAULT_MAX_PDP_RESET_FAIL);
-            if (mPdpResetCount < maxPdpReset) {
-                mPdpResetCount++;
-                EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
-                if (DBG) log("doRecovery() cleanup all connections mPdpResetCount < max");
+            // Go through a series of recovery steps, each action transitions to the next action
+            int recoveryAction = getRecoveryAction();
+            switch (recoveryAction) {
+            case RecoveryAction.GET_DATA_CALL_LIST:
+                EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_GET_DATA_CALL_LIST,
+                        mSentSinceLastRecv);
+                if (DBG) log("doRecovery() get data call list");
+                mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED));
+                putRecoveryAction(RecoveryAction.CLEANUP);
+                break;
+            case RecoveryAction.CLEANUP:
+                EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_CLEANUP, mSentSinceLastRecv);
+                if (DBG) log("doRecovery() cleanup all connections");
                 cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
-            } else {
-                mPdpResetCount = 0;
-                switch (mRecoveryAction) {
-                case REREGISTER:
-                    EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
-                    if (DBG) log("doRecovery() re-register getting preferred network type");
-                    mPhone.getServiceStateTracker().reRegisterNetwork(null);
-                    mRecoveryAction = RecoveryAction.RADIO_RESTART;
-                    break;
-                case RADIO_RESTART:
-                    EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
-                    if (DBG) log("restarting radio");
-                    mRecoveryAction = RecoveryAction.RADIO_RESET;
-                    restartRadio();
-                    break;
-                case RADIO_RESET:
-                    // This is in case radio restart has not recovered the data.
-                    // It will set an additional "gsm.radioreset" property to tell
-                    // RIL or system to take further action.
-                    // The implementation of hard reset recovery action is up to OEM product.
-                    // Once gsm.radioreset property is consumed, it is expected to set back
-                    // to false by RIL.
-                    EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1);
-                    if (DBG) log("restarting radio with reset indication");
-                    SystemProperties.set("gsm.radioreset", "true");
-                    // give 1 sec so property change can be notified.
-                    try {
-                        Thread.sleep(1000);
-                    } catch (InterruptedException e) {}
-                    restartRadio();
-                    break;
-                default:
-                    throw new RuntimeException("doRecovery: Invalid mRecoveryAction " +
-                        mRecoveryAction);
-                }
+                putRecoveryAction(RecoveryAction.REREGISTER);
+                break;
+            case RecoveryAction.REREGISTER:
+                EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_REREGISTER,
+                        mSentSinceLastRecv);
+                if (DBG) log("doRecovery() re-register");
+                mPhone.getServiceStateTracker().reRegisterNetwork(null);
+                putRecoveryAction(RecoveryAction.RADIO_RESTART);
+                break;
+            case RecoveryAction.RADIO_RESTART:
+                EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_RADIO_RESTART,
+                        mSentSinceLastRecv);
+                if (DBG) log("restarting radio");
+                putRecoveryAction(RecoveryAction.RADIO_RESTART_WITH_PROP);
+                restartRadio();
+                break;
+            case RecoveryAction.RADIO_RESTART_WITH_PROP:
+                // This is in case radio restart has not recovered the data.
+                // It will set an additional "gsm.radioreset" property to tell
+                // RIL or system to take further action.
+                // The implementation of hard reset recovery action is up to OEM product.
+                // Once gsm.radioreset property is consumed, it is expected to set back
+                // to false by RIL.
+                EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_RADIO_RESTART_WITH_PROP, -1);
+                if (DBG) log("restarting radio with gsm.radioreset to true");
+                SystemProperties.set("gsm.radioreset", "true");
+                // give 1 sec so property change can be notified.
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {}
+                restartRadio();
+                putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST);
+                break;
+            default:
+                throw new RuntimeException("doRecovery: Invalid recoveryAction=" +
+                    recoveryAction);
             }
-        } else {
-            if (DBG) log("doRecovery(): ignore, we're not connected");
         }
     }
 
@@ -1340,119 +1373,130 @@
         SystemProperties.set("net.ppp.reset-by-timeout", String.valueOf(reset+1));
     }
 
+
+    private void updateDataStallInfo() {
+        long sent, received;
+
+        TxRxSum preTxRxSum = new TxRxSum(mDataStallTxRxSum);
+        mDataStallTxRxSum.updateTxRxSum();
+
+        if (VDBG) {
+            log("updateDataStallInfo: mDataStallTxRxSum=" + mDataStallTxRxSum +
+                    " preTxRxSum=" + preTxRxSum);
+        }
+
+        sent = mDataStallTxRxSum.txPkts - preTxRxSum.txPkts;
+        received = mDataStallTxRxSum.rxPkts - preTxRxSum.rxPkts;
+
+        if (VDBG) {
+            if (SystemProperties.getBoolean("radio.test.data.stall", false)) {
+                log("updateDataStallInfo: radio.test.data.stall true received = 0;");
+                received = 0;
+            }
+        }
+        if ( sent > 0 && received > 0 ) {
+            if (VDBG) log("updateDataStallInfo: IN/OUT");
+            mSentSinceLastRecv = 0;
+            putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST);
+        } else if (sent > 0 && received == 0) {
+            if (mPhone.getState() == Phone.State.IDLE) {
+                mSentSinceLastRecv += sent;
+            } else {
+                mSentSinceLastRecv = 0;
+            }
+            if (DBG) {
+                log("updateDataStallInfo: OUT sent=" + sent +
+                        " mSentSinceLastRecv=" + mSentSinceLastRecv);
+            }
+        } else if (sent == 0 && received > 0) {
+            if (VDBG) log("updateDataStallInfo: IN");
+            mSentSinceLastRecv = 0;
+            putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST);
+        } else {
+            if (VDBG) log("updateDataStallInfo: NONE");
+        }
+    }
+
+    @Override
+    protected void onDataStallAlarm(int tag) {
+        if (mDataStallAlarmTag != tag) {
+            if (DBG) {
+                log("onDataStallAlarm: ignore, tag=" + tag + " expecting " + mDataStallAlarmTag);
+            }
+            return;
+        }
+        updateDataStallInfo();
+
+        int hangWatchdogTrigger = Settings.Secure.getInt(mResolver,
+                Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
+                NUMBER_SENT_PACKETS_OF_HANG);
+
+        if (mSentSinceLastRecv >= hangWatchdogTrigger) {
+            if (DBG) {
+                log("onDataStallAlarm: tag=" + tag + " do recovery action=" + getRecoveryAction());
+            }
+            sendMessage(obtainMessage(EVENT_DO_RECOVERY));
+        } else {
+            if (VDBG) {
+                log("onDataStallAlarm: tag=" + tag + " Sent " + String.valueOf(mSentSinceLastRecv) +
+                    " pkts since last received, < watchdogTrigger=" + hangWatchdogTrigger);
+            }
+        }
+        startDataStallAlarm();
+    }
+
+
+    private void updateDataActivity() {
+        long sent, received;
+
+        Activity newActivity;
+
+        TxRxSum preTxRxSum = new TxRxSum(mTxPkts, mRxPkts);
+        TxRxSum curTxRxSum = new TxRxSum();
+        curTxRxSum.updateTxRxSum();
+        mTxPkts = curTxRxSum.txPkts;
+        mRxPkts = curTxRxSum.rxPkts;
+
+        if (VDBG) {
+            log("updateDataActivity: curTxRxSum=" + curTxRxSum + " preTxRxSum=" + preTxRxSum);
+        }
+
+        if (mNetStatPollEnabled && (preTxRxSum.txPkts > 0 || preTxRxSum.rxPkts > 0)) {
+            sent = mTxPkts - preTxRxSum.txPkts;
+            received = mRxPkts - preTxRxSum.rxPkts;
+
+            if (VDBG) log("updateDataActivity: sent=" + sent + " received=" + received);
+            if ( sent > 0 && received > 0 ) {
+                newActivity = Activity.DATAINANDOUT;
+            } else if (sent > 0 && received == 0) {
+                newActivity = Activity.DATAOUT;
+            } else if (sent == 0 && received > 0) {
+                newActivity = Activity.DATAIN;
+            } else {
+                newActivity = Activity.NONE;
+            }
+
+            if (mActivity != newActivity && mIsScreenOn) {
+                if (VDBG) log("updateDataActivity: newActivity=" + newActivity);
+                mActivity = newActivity;
+                mPhone.notifyDataActivity();
+            }
+        }
+    }
+
     private Runnable mPollNetStat = new Runnable()
     {
-
+        @Override
         public void run() {
-            long sent, received;
-            long preTxPkts = -1, preRxPkts = -1;
+            updateDataActivity();
 
-            Activity newActivity;
-
-            preTxPkts = mTxPkts;
-            preRxPkts = mRxPkts;
-
-            long txSum = 0, rxSum = 0;
-            for (ApnContext apnContext : mApnContexts.values()) {
-                if (apnContext.getState() == State.CONNECTED) {
-                    DataConnectionAc dcac = apnContext.getDataConnectionAc();
-                    if (dcac == null) continue;
-
-                    LinkProperties linkProp = dcac.getLinkPropertiesSync();
-                    if (linkProp == null) continue;
-
-                    String iface = linkProp.getInterfaceName();
-
-                    if (iface != null) {
-                        long stats = TrafficStats.getTxPackets(iface);
-                        if (stats > 0) txSum += stats;
-                        stats = TrafficStats.getRxPackets(iface);
-                        if (stats > 0) rxSum += stats;
-                    }
-                }
-            }
-
-            mTxPkts = txSum;
-            mRxPkts = rxSum;
-
-            // log("tx " + mTxPkts + " rx " + mRxPkts);
-
-            if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
-                sent = mTxPkts - preTxPkts;
-                received = mRxPkts - preRxPkts;
-
-                if ( sent > 0 && received > 0 ) {
-                    mSentSinceLastRecv = 0;
-                    newActivity = Activity.DATAINANDOUT;
-                    mPdpResetCount = 0;
-                    mRecoveryAction = RecoveryAction.REREGISTER;
-                } else if (sent > 0 && received == 0) {
-                    if (mPhone.getState() == Phone.State.IDLE) {
-                        mSentSinceLastRecv += sent;
-                    } else {
-                        mSentSinceLastRecv = 0;
-                    }
-                    newActivity = Activity.DATAOUT;
-                } else if (sent == 0 && received > 0) {
-                    mSentSinceLastRecv = 0;
-                    newActivity = Activity.DATAIN;
-                    mPdpResetCount = 0;
-                    mRecoveryAction = RecoveryAction.REREGISTER;
-                } else if (sent == 0 && received == 0) {
-                    newActivity = Activity.NONE;
-                } else {
-                    mSentSinceLastRecv = 0;
-                    newActivity = Activity.NONE;
-                }
-
-                if (mActivity != newActivity && mIsScreenOn) {
-                    mActivity = newActivity;
-                    mPhone.notifyDataActivity();
-                }
-            }
-
-            int watchdogTrigger = Settings.Secure.getInt(mResolver,
-                    Settings.Secure.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
-                    NUMBER_SENT_PACKETS_OF_HANG);
-
-            if (mSentSinceLastRecv >= watchdogTrigger) {
-                // we already have NUMBER_SENT_PACKETS sent without ack
-                if (mNoRecvPollCount == 0) {
-                    EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
-                            mSentSinceLastRecv);
-                }
-
-                int noRecvPollLimit = Settings.Secure.getInt(mResolver,
-                        Settings.Secure.PDP_WATCHDOG_ERROR_POLL_COUNT, NO_RECV_POLL_LIMIT);
-
-                if (mNoRecvPollCount < noRecvPollLimit) {
-                    // It's possible the PDP context went down and we weren't notified.
-                    // Start polling the context list in an attempt to recover.
-                    if (DBG) log("Polling: no DATAIN in a while; polling PDP");
-                    mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED));
-
-                    mNoRecvPollCount++;
-
-                    // Slow down the poll interval to let things happen
-                    mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
-                            Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
-                            POLL_NETSTAT_SLOW_MILLIS);
-                } else {
-                    if (DBG) log("Polling: Sent " + String.valueOf(mSentSinceLastRecv) +
-                                        " pkts since last received start recovery process");
-                    mNoRecvPollCount = 0;
-                    sendMessage(obtainMessage(EVENT_START_RECOVERY));
-                }
+            if (mIsScreenOn) {
+                mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
+                        Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
             } else {
-                mNoRecvPollCount = 0;
-                if (mIsScreenOn) {
-                    mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
-                            Settings.Secure.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
-                } else {
-                    mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
-                            Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
-                            POLL_NETSTAT_SCREEN_OFF_MILLIS);
-                }
+                mNetStatPollPeriod = Settings.Secure.getInt(mResolver,
+                        Settings.Secure.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
+                        POLL_NETSTAT_SCREEN_OFF_MILLIS);
             }
 
             if (mNetStatPollEnabled) {
@@ -1564,6 +1608,41 @@
 
     }
 
+    private void startDataStallAlarm() {
+        int delayInMs = Settings.Secure.getInt(mResolver,
+                            Settings.Secure.DATA_STALL_ALARM_DELAY_IN_MS,
+                            DATA_STALL_ALARM_DELAY_IN_MS_DEFAULT);
+        mDataStallAlarmTag += 1;
+        if (DBG) {
+            log("startDataStallAlarm: tag=" + mDataStallAlarmTag +
+                    " delay=" + (delayInMs / 1000) + "s");
+        }
+        AlarmManager am =
+            (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+
+        Intent intent = new Intent(INTENT_DATA_STALL_ALARM);
+        intent.putExtra(DATA_STALL_ALARM_TAG_EXTRA, mDataStallAlarmTag);
+        mDataStallAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                SystemClock.elapsedRealtime() + delayInMs, mDataStallAlarmIntent);
+    }
+
+    private void stopDataStallAlarm() {
+        AlarmManager am =
+            (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+
+        if (DBG) {
+            log("stopDataStallAlarm: current tag=" + mDataStallAlarmTag +
+                    " mDataStallAlarmIntent=" + mDataStallAlarmIntent);
+        }
+        mDataStallAlarmTag += 1;
+        if (mDataStallAlarmIntent != null) {
+            am.cancel(mDataStallAlarmIntent);
+            mDataStallAlarmIntent = null;
+        }
+    }
+
     private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
                               ApnContext apnContext) {
         if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
@@ -1928,6 +2007,7 @@
         if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
             if (DBG) log("onVoiceCallStarted stop polling");
             stopNetStatPoll();
+            stopDataStallAlarm();
             notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
         }
     }
@@ -1938,6 +2018,7 @@
         if (isConnected()) {
             if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 startNetStatPoll();
+                startDataStallAlarm();
                 notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
             } else {
                 // clean slate after call end.
@@ -2249,11 +2330,7 @@
                 onPollPdp();
                 break;
 
-            case EVENT_START_NETSTAT_POLL:
-                startNetStatPoll();
-                break;
-
-            case EVENT_START_RECOVERY:
+            case EVENT_DO_RECOVERY:
                 doRecovery();
                 break;
 
@@ -2270,6 +2347,7 @@
                  */
                 if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
                 stopNetStatPoll();
+                stopDataStallAlarm();
                 mIsPsRestricted = true;
                 break;
 
@@ -2282,6 +2360,7 @@
                 mIsPsRestricted  = false;
                 if (isConnected()) {
                     startNetStatPoll();
+                    startDataStallAlarm();
                 } else {
                     // TODO: Should all PDN states be checked to fail?
                     if (mState == State.FAILED) {
diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml
index aa663f3..e88f4fb 100644
--- a/tests/FrameworkPerf/AndroidManifest.xml
+++ b/tests/FrameworkPerf/AndroidManifest.xml
@@ -13,6 +13,10 @@
         </activity>
         <service android:name="SchedulerService">
         </service>
+        <service android:name="TestService" android:process=":test">
+        </service>
+        <service android:name="LocalTestService">
+        </service>
         <receiver android:name="Receiver" android:exported="true">
         </receiver>
     </application>
diff --git a/tests/FrameworkPerf/res/layout/main.xml b/tests/FrameworkPerf/res/layout/main.xml
index 62b1a7a..7812648 100644
--- a/tests/FrameworkPerf/res/layout/main.xml
+++ b/tests/FrameworkPerf/res/layout/main.xml
@@ -91,6 +91,11 @@
             android:layout_height="wrap_content"
             android:text="@string/stop"
             />
+        <CheckBox android:id="@+id/local"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Local"
+            />
     </LinearLayout>
 
     <TextView android:id="@+id/log"
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 3979902..175f227 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -17,191 +17,123 @@
 package com.android.frameworkperf;
 
 import android.app.Activity;
-import android.content.Context;
+import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
+import android.content.ServiceConnection;
+import android.os.Binder;
 import android.os.Bundle;
-import android.os.FileUtils;
 import android.os.Handler;
-import android.os.Looper;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
 import android.os.PowerManager;
-import android.os.Process;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
+import android.os.RemoteException;
 import android.util.Log;
-import android.util.Xml;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.CheckBox;
 import android.widget.Spinner;
 import android.widget.TextView;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.util.ArrayList;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 /**
  * So you thought sync used up your battery life.
  */
 public class FrameworkPerfActivity extends Activity
         implements AdapterView.OnItemSelectedListener {
     static final String TAG = "Perf";
-
-    final Handler mHandler = new Handler();
+    static final boolean DEBUG = false;
 
     Spinner mFgSpinner;
     Spinner mBgSpinner;
     TextView mTestTime;
     Button mStartButton;
     Button mStopButton;
+    CheckBox mLocalCheckBox;
     TextView mLog;
     PowerManager.WakeLock mPartialWakeLock;
 
     long mMaxRunTime = 5000;
     boolean mStarted;
 
-    final TestRunner mRunner = new TestRunner();
-
-    final Op[] mOpPairs = new Op[] {
-            new MethodCallOp(), new NoOp(),
-            new MethodCallOp(), new CpuOp(),
-            new MethodCallOp(), new SchedulerOp(),
-            new MethodCallOp(), new GcOp(),
-            new MethodCallOp(), new CreateFileOp(),
-            new MethodCallOp(), new CreateWriteFileOp(),
-            new MethodCallOp(), new CreateWriteSyncFileOp(),
-            new MethodCallOp(), new WriteFileOp(),
-            new MethodCallOp(), new ReadFileOp(),
-            new SchedulerOp(), new SchedulerOp(),
-            new GcOp(), new NoOp(),
-            new IpcOp(), new NoOp(),
-            new IpcOp(), new CpuOp(),
-            new IpcOp(), new SchedulerOp(),
-            new IpcOp(), new GcOp(),
-            new IpcOp(), new CreateFileOp(),
-            new IpcOp(), new CreateWriteFileOp(),
-            new IpcOp(), new CreateWriteSyncFileOp(),
-            new IpcOp(), new WriteFileOp(),
-            new IpcOp(), new ReadFileOp(),
-            new CreateFileOp(), new NoOp(),
-            new CreateWriteFileOp(), new NoOp(),
-            new CreateWriteSyncFileOp(), new NoOp(),
-            new WriteFileOp(), new NoOp(),
-            new ReadFileOp(), new NoOp(),
-            new WriteFileOp(), new CreateWriteFileOp(),
-            new ReadFileOp(), new CreateWriteFileOp(),
-            new WriteFileOp(), new CreateWriteSyncFileOp(),
-            new ReadFileOp(), new CreateWriteSyncFileOp(),
-            new WriteFileOp(), new WriteFileOp(),
-            new WriteFileOp(), new ReadFileOp(),
-            new ReadFileOp(), new WriteFileOp(),
-            new ReadFileOp(), new ReadFileOp(),
-            new OpenXmlResOp(), new NoOp(),
-            new ReadXmlAttrsOp(), new NoOp(),
-            new ParseXmlResOp(), new NoOp(),
-            new ParseLargeXmlResOp(), new NoOp(),
-            new LayoutInflaterOp(), new NoOp(),
-            new LayoutInflaterLargeOp(), new NoOp(),
-            new LayoutInflaterViewOp(), new NoOp(),
-            new LayoutInflaterButtonOp(), new NoOp(),
-            new LayoutInflaterImageButtonOp(), new NoOp(),
-            new CreateBitmapOp(), new NoOp(),
-            new CreateRecycleBitmapOp(), new NoOp(),
-            new LoadSmallBitmapOp(), new NoOp(),
-            new LoadRecycleSmallBitmapOp(), new NoOp(),
-            new LoadLargeBitmapOp(), new NoOp(),
-            new LoadRecycleLargeBitmapOp(), new NoOp(),
-            new LoadSmallScaledBitmapOp(), new NoOp(),
-            new LoadLargeScaledBitmapOp(), new NoOp(),
-    };
-
-    final Op[] mAvailOps = new Op[] {
-            null,
-            new NoOp(),
-            new CpuOp(),
-            new SchedulerOp(),
-            new MethodCallOp(),
-            new IpcOp(),
-            new CreateFileOp(),
-            new CreateWriteFileOp(),
-            new CreateWriteSyncFileOp(),
-            new WriteFileOp(),
-            new ReadFileOp(),
-            new OpenXmlResOp(),
-            new ReadXmlAttrsOp(),
-            new ParseXmlResOp(),
-            new ParseLargeXmlResOp(),
-            new LayoutInflaterOp(),
-            new LayoutInflaterLargeOp(),
-            new LayoutInflaterViewOp(),
-            new LayoutInflaterButtonOp(),
-            new LayoutInflaterImageButtonOp(),
-            new CreateBitmapOp(),
-            new CreateRecycleBitmapOp(),
-            new LoadSmallBitmapOp(),
-            new LoadRecycleSmallBitmapOp(),
-            new LoadLargeBitmapOp(),
-            new LoadRecycleLargeBitmapOp(),
-            new LoadSmallScaledBitmapOp(),
-            new LoadLargeScaledBitmapOp(),
-    };
-
     final String[] mAvailOpLabels;
     final String[] mAvailOpDescriptions;
 
-    Op mFgTest;
-    Op mBgTest;
+    int mFgTestIndex = -1;
+    int mBgTestIndex = -1;
+    TestService.Op mFgTest;
+    TestService.Op mBgTest;
     int mCurOpIndex = 0;
-
-    class RunResult {
-        final String name;
-        final String fgLongName;
-        final String bgLongName;
-        final long fgTime;
-        final long fgOps;
-        final long bgTime;
-        final long bgOps;
-
-        RunResult(TestRunner op) {
-            name = op.getName();
-            fgLongName = op.getForegroundLongName();
-            bgLongName = op.getBackgroundLongName();
-            fgTime = op.getForegroundTime();
-            fgOps = op.getForegroundOps();
-            bgTime = op.getBackgroundTime();
-            bgOps = op.getBackgroundOps();
-        }
-
-        float getFgMsPerOp() {
-            return fgOps != 0 ? (fgTime / (float)fgOps) : 0;
-        }
-
-        float getBgMsPerOp() {
-            return bgOps != 0 ? (bgTime / (float)bgOps) : 0;
-        }
-    }
+    TestConnection mCurConnection;
+    boolean mConnectionBound;
 
     final ArrayList<RunResult> mResults = new ArrayList<RunResult>();
 
+    class TestConnection implements ServiceConnection, IBinder.DeathRecipient {
+        Messenger mService;
+        boolean mLinked;
+
+        @Override public void onServiceConnected(ComponentName name, IBinder service) {
+            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_DO_NEXT_TEST = 1000;
+
+    final Handler mHandler = new Handler() {
+        @Override public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case TestService.RES_TEST_FINISHED: {
+                    Bundle bundle = (Bundle)msg.obj;
+                    bundle.setClassLoader(getClassLoader());
+                    RunResult res = (RunResult)bundle.getParcelable("res");
+                    completeCurOp(res);
+                } break;
+                case MSG_DO_NEXT_TEST: {
+                    startCurOp();
+                } break;
+            }
+        }
+    };
+
+    final Messenger mMessenger = new Messenger(mHandler);
+
     public FrameworkPerfActivity() {
-        mAvailOpLabels = new String[mAvailOps.length];
-        mAvailOpDescriptions = new String[mAvailOps.length];
-        for (int i=0; i<mAvailOps.length; i++) {
-            Op op = mAvailOps[i];
+        mAvailOpLabels = new String[TestService.mAvailOps.length];
+        mAvailOpDescriptions = new String[TestService.mAvailOps.length];
+        for (int i=0; i<TestService.mAvailOps.length; i++) {
+            TestService.Op op = TestService.mAvailOps[i];
             if (op == null) {
                 mAvailOpLabels[i] = "All";
                 mAvailOpDescriptions[i] = "All tests";
@@ -251,6 +183,7 @@
             }
         });
         mStopButton.setEnabled(false);
+        mLocalCheckBox = (CheckBox)findViewById(R.id.local);
 
         mLog = (TextView)findViewById(R.id.log);
 
@@ -262,11 +195,13 @@
     @Override
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
         if (parent == mFgSpinner || parent == mBgSpinner) {
-            Op op = mAvailOps[position];
+            TestService.Op op = TestService.mAvailOps[position];
             if (parent == mFgSpinner) {
+                mFgTestIndex = position;
                 mFgTest = op;
                 ((TextView)findViewById(R.id.fgtext)).setText(mAvailOpDescriptions[position]);
             } else {
+                mBgTestIndex = position;
                 mBgTest = op;
                 ((TextView)findViewById(R.id.bgtext)).setText(mAvailOpDescriptions[position]);
             }
@@ -291,64 +226,140 @@
         }
     }
 
-    void startCurOp() {
-        Op fgOp, bgOp;
-        if (mFgTest == null && mBgTest == null) {
-            fgOp = mOpPairs[mCurOpIndex];
-            bgOp = mOpPairs[mCurOpIndex+1];
-        } else if (mFgTest != null && mBgTest != null) {
-            fgOp = mFgTest;
-            bgOp = mBgTest;
-        } else if (mFgTest != null) {
-            // Skip null test.
-            if (mCurOpIndex == 0) {
-                mCurOpIndex = 1;
-            }
-            fgOp = mFgTest;
-            bgOp = mAvailOps[mCurOpIndex];
+    void dispatchCurOp(TestConnection conn) {
+        if (mCurConnection != conn) {
+            Log.w(TAG, "Dispatching on invalid connection: " + conn);
+            return;
+        }
+        TestArgs args = new TestArgs();
+        args.maxTime = mMaxRunTime;
+        if (mFgTestIndex == 0 && mBgTestIndex == 0) {
+            args.combOp = mCurOpIndex;
+        } else if (mFgTestIndex != 0 && mBgTestIndex != 0) {
+            args.fgOp = mFgTestIndex;
+            args.bgOp = mBgTestIndex;
         } else {
             // Skip null test.
             if (mCurOpIndex == 0) {
                 mCurOpIndex = 1;
             }
-            fgOp = mAvailOps[mCurOpIndex];
-            bgOp = mBgTest;
-        }
-        mRunner.run(mHandler, fgOp, bgOp, new Runnable() {
-            @Override public void run() {
-                RunResult result = new RunResult(mRunner);
-                log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)",
-                        result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime,
-                        result.bgOps, result.getBgMsPerOp(), result.bgTime));
-                mResults.add(result);
-                if (!mStarted) {
-                    log("Stop");
-                    stopRunning();
-                    return;
-                }
-                if (mFgTest != null && mBgTest != null) {
-                    log("Finished");
-                    stopRunning();
-                    return;
-                }
-                if (mFgTest == null && mBgTest == null) {
-                    mCurOpIndex+=2;
-                    if (mCurOpIndex >= mOpPairs.length) {
-                        log("Finished");
-                        stopRunning();
-                        return;
-                    }
-                } else {
-                    mCurOpIndex++;
-                    if (mCurOpIndex >= mAvailOps.length) {
-                        log("Finished");
-                        stopRunning();
-                        return;
-                    }
-                }
-                startCurOp();
+            if (mFgTestIndex != 0) {
+                args.fgOp = mFgTestIndex;
+                args.bgOp = mCurOpIndex;
+            } else {
+                args.fgOp = mCurOpIndex;
+                args.bgOp = mFgTestIndex;
             }
-        });
+        }
+        Bundle bundle = new Bundle();
+        bundle.putParcelable("args", args);
+        Message msg = Message.obtain(null, TestService.CMD_START_TEST, bundle);
+        msg.replyTo = mMessenger;
+        try {
+            conn.mService.send(msg);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failure communicating with service", e);
+        }
+    }
+
+    void completeCurOp(RunResult result) {
+        log(String.format("%s: fg=%d*%gms/op (%dms) / bg=%d*%gms/op (%dms)",
+                result.name, result.fgOps, result.getFgMsPerOp(), result.fgTime,
+                result.bgOps, result.getBgMsPerOp(), result.bgTime));
+        mResults.add(result);
+        if (!mStarted) {
+            log("Stop");
+            stopRunning();
+            return;
+        }
+        if (mFgTest != null && mBgTest != null) {
+            log("Finished");
+            stopRunning();
+            return;
+        }
+        if (mFgTest == null && mBgTest == null) {
+            mCurOpIndex+=2;
+            if (mCurOpIndex >= TestService.mOpPairs.length) {
+                log("Finished");
+                stopRunning();
+                return;
+            }
+        } else {
+            mCurOpIndex++;
+            if (mCurOpIndex >= TestService.mAvailOps.length) {
+                log("Finished");
+                stopRunning();
+                return;
+            }
+        }
+        startCurOp();
+    }
+
+    void disconnect() {
+        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);
+                try {
+                    conn.mService.send(msg);
+                    return;
+                } catch (RemoteException 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_DO_NEXT_TEST);
+            mCurConnection = new TestConnection();
+            Intent intent;
+            if (mLocalCheckBox.isChecked()) {
+                intent = new Intent(this, LocalTestService.class);
+            } 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;
+        }
     }
 
     void startRunning() {
@@ -357,6 +368,7 @@
             mStarted = true;
             mStartButton.setEnabled(false);
             mStopButton.setEnabled(true);
+            mLocalCheckBox.setEnabled(false);
             mTestTime.setEnabled(false);
             mFgSpinner.setEnabled(false);
             mBgSpinner.setEnabled(false);
@@ -371,9 +383,11 @@
 
     void stopRunning() {
         if (mStarted) {
+            disconnect();
             mStarted = false;
             mStartButton.setEnabled(true);
             mStopButton.setEnabled(false);
+            mLocalCheckBox.setEnabled(true);
             mTestTime.setEnabled(true);
             mFgSpinner.setEnabled(true);
             mBgSpinner.setEnabled(true);
@@ -412,842 +426,4 @@
         mLog.setText(mLog.getText() + "\n" + s);
         Log.i(TAG, s);
     }
-
-    enum BackgroundMode {
-        NOTHING,
-        CPU,
-        SCHEDULER
-    };
-
-    public class TestRunner {
-        Handler mHandler;
-        Op mForegroundOp;
-        Op mBackgroundOp;
-        Runnable mDoneCallback;
-
-        RunnerThread mBackgroundThread;
-        RunnerThread mForegroundThread;
-        long mStartTime;
-
-        boolean mBackgroundRunning;
-        boolean mForegroundRunning;
-
-        long mBackgroundEndTime;
-        long mBackgroundOps;
-        long mForegroundEndTime;
-        long mForegroundOps;
-
-        public TestRunner() {
-        }
-
-        public String getForegroundName() {
-            return mForegroundOp.getName();
-        }
-
-        public String getBackgroundName() {
-            return mBackgroundOp.getName();
-        }
-
-        public String getName() {
-            String fgName = mForegroundOp.getName();
-            String bgName = mBackgroundOp.getName();
-            StringBuilder res = new StringBuilder();
-            if (fgName != null) {
-                res.append(fgName);
-                res.append("Fg");
-            }
-            if (bgName != null) {
-                res.append(bgName);
-                res.append("Bg");
-            }
-            return res.toString();
-        }
-
-        public String getForegroundLongName() {
-            return mForegroundOp.getLongName();
-        }
-
-        public String getBackgroundLongName() {
-            return mBackgroundOp.getLongName();
-        }
-
-        public void run(Handler handler, Op foreground, Op background, Runnable doneCallback) {
-            mHandler = handler;
-            mForegroundOp = foreground;
-            mBackgroundOp = background;
-            mDoneCallback = doneCallback;
-            mBackgroundThread = new RunnerThread("background", new Runnable() {
-                @Override public void run() {
-                    boolean running;
-                    int ops = 0;
-                    do {
-                        running = mBackgroundOp.onRun();
-                        ops++;
-                    } while (evalRepeat(running, true) && running);
-                    mBackgroundEndTime = SystemClock.uptimeMillis();
-                    mBackgroundOps = ops * mBackgroundOp.getOpsPerRun();
-                    threadFinished(false);
-                }
-            }, Process.THREAD_PRIORITY_BACKGROUND);
-            mForegroundThread = new RunnerThread("background", new Runnable() {
-                @Override public void run() {
-                    boolean running;
-                    int ops = 0;
-                    do {
-                        running = mForegroundOp.onRun();
-                        ops++;
-                    } while (evalRepeat(true, running) && running);
-                    mForegroundEndTime = SystemClock.uptimeMillis();
-                    mForegroundOps = ops * mForegroundOp.getOpsPerRun();
-                    threadFinished(true);
-                }
-            }, Process.THREAD_PRIORITY_FOREGROUND);
-
-            mForegroundOp.onInit(FrameworkPerfActivity.this, true);
-            mBackgroundOp.onInit(FrameworkPerfActivity.this, false);
-
-            synchronized (this) {
-                mStartTime = SystemClock.uptimeMillis();
-                mBackgroundRunning = true;
-                mForegroundRunning = true;
-            }
-
-            mBackgroundThread.start();
-            mForegroundThread.start();
-        }
-
-        public long getForegroundTime() {
-            return mForegroundEndTime-mStartTime;
-        }
-
-        public long getForegroundOps() {
-            return mForegroundOps;
-        }
-
-        public long getBackgroundTime() {
-            return mBackgroundEndTime-mStartTime;
-        }
-
-        public long getBackgroundOps() {
-            return mBackgroundOps;
-        }
-
-        private boolean evalRepeat(boolean bgRunning, boolean fgRunning) {
-            synchronized (this) {
-                if (!bgRunning) {
-                    mBackgroundRunning = false;
-                }
-                if (!fgRunning) {
-                    mForegroundRunning = false;
-                }
-                if (!mBackgroundRunning && !mForegroundRunning) {
-                    return false;
-                }
-                long now = SystemClock.uptimeMillis();
-                if (now > (mStartTime+mMaxRunTime)) {
-                    return false;
-                }
-                return true;
-            }
-        }
-
-        private void threadFinished(boolean foreground) {
-            synchronized (this) {
-                if (foreground) {
-                    mForegroundRunning = false;
-                } else {
-                    mBackgroundRunning = false;
-                }
-                if (!mBackgroundRunning && !mForegroundRunning) {
-                    mHandler.post(new Runnable() {
-                        @Override public void run() {
-                            mForegroundOp.onTerm(FrameworkPerfActivity.this);
-                            mBackgroundOp.onTerm(FrameworkPerfActivity.this);
-                            if (mDoneCallback != null) {
-                                mDoneCallback.run();
-                            }
-                        }
-                    });
-                }
-            }
-        }
-    }
-
-    class RunnerThread extends Thread {
-        private final Runnable mOp;
-        private final int mPriority;
-
-        RunnerThread(String name, Runnable op, int priority) {
-            super(name);
-            mOp = op;
-            mPriority = priority;
-        }
-
-        public void run() {
-            Process.setThreadPriority(mPriority);
-            mOp.run();
-        }
-    }
-
-    static public abstract class Op {
-        final String mName;
-        final String mLongName;
-
-        public Op(String name, String longName) {
-            mName = name;
-            mLongName = longName;
-        }
-
-        public String getName() {
-            return mName;
-        }
-
-        public String getLongName() {
-            return mLongName;
-        }
-
-        void onInit(Context context, boolean foreground) {
-        }
-
-        abstract boolean onRun();
-
-        void onTerm(Context context) {
-        }
-
-        int getOpsPerRun() {
-            return 1;
-        }
-    }
-
-    static class NoOp extends Op {
-        NoOp() {
-            super(null, "Nothing");
-        }
-
-        boolean onRun() {
-            return false;
-        }
-
-        int getOpsPerRun() {
-            return 0;
-        }
-    }
-
-    static class CpuOp extends Op {
-        CpuOp() {
-            super("CPU", "Consume CPU");
-        }
-
-        boolean onRun() {
-            return true;
-        }
-    }
-
-    static class SchedulerOp extends Op {
-        SchedulerOp() {
-            super("Sched", "Change scheduler group");
-        }
-
-        boolean onRun() {
-            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-            return true;
-        }
-    }
-
-    static class GcOp extends Op {
-        GcOp() {
-            super("Gc", "Run garbage collector");
-        }
-
-        boolean onRun() {
-            byte[] stuff = new byte[1024*1024];
-            return true;
-        }
-    }
-
-    static class MethodCallOp extends Op {
-        MethodCallOp() {
-            super("MethodCall", "Method call");
-        }
-
-        boolean onRun() {
-            final int N = getOpsPerRun();
-            for (int i=0; i<N; i++) {
-                someFunc(i);
-            }
-            return true;
-        }
-
-        int someFunc(int foo) {
-            return 0;
-        }
-
-        int getOpsPerRun() {
-            return 500;
-        }
-    }
-
-    static class IpcOp extends Op {
-        PackageManager mPm;
-        String mProcessName;
-
-        IpcOp() {
-            super("Ipc", "IPC to system process");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mPm = context.getPackageManager();
-            mProcessName = context.getApplicationInfo().processName;
-        }
-
-        boolean onRun() {
-            final int N = getOpsPerRun();
-            for (int i=0; i<N; i++) {
-                mPm.queryContentProviders(mProcessName, Process.myUid(), 0);
-            }
-            return true;
-        }
-
-        int getOpsPerRun() {
-            return 100;
-        }
-    }
-
-    static class OpenXmlResOp extends Op {
-        Context mContext;
-
-        OpenXmlResOp() {
-            super("OpenXmlRes", "Open (and close) an XML resource");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            XmlResourceParser parser = mContext.getResources().getLayout(R.xml.simple);
-            parser.close();
-            return true;
-        }
-    }
-
-    static class ReadXmlAttrsOp extends Op {
-        Context mContext;
-        XmlResourceParser mParser;
-        AttributeSet mAttrs;
-
-        ReadXmlAttrsOp() {
-            super("ReadXmlAttrs", "Read attributes from an XML tag");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-            mParser = mContext.getResources().getLayout(R.xml.simple);
-            mAttrs = Xml.asAttributeSet(mParser);
-
-            int eventType;
-            try {
-                // Find the first <item> tag.
-                eventType = mParser.getEventType();
-                String tagName;
-                do {
-                    if (eventType == XmlPullParser.START_TAG) {
-                        tagName = mParser.getName();
-                        if (tagName.equals("item")) {
-                            break;
-                        }
-                    }
-                    eventType = mParser.next();
-                } while (eventType != XmlPullParser.END_DOCUMENT);
-            } catch (XmlPullParserException e) {
-                throw new RuntimeException("I died", e);
-            } catch (IOException e) {
-                throw new RuntimeException("I died", e);
-            }
-        }
-
-        void onTerm(Context context) {
-            mParser.close();
-        }
-
-        boolean onRun() {
-            TypedArray a = mContext.obtainStyledAttributes(mAttrs,
-                    com.android.internal.R.styleable.MenuItem);
-            a.recycle();
-            return true;
-        }
-    }
-
-    static class ParseXmlResOp extends Op {
-        Context mContext;
-
-        ParseXmlResOp() {
-            super("ParseXmlRes", "Parse compiled XML resource");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            SimpleInflater inf = new SimpleInflater(mContext);
-            inf.inflate(R.xml.simple);
-            return true;
-        }
-    }
-
-    static class ParseLargeXmlResOp extends Op {
-        Context mContext;
-
-        ParseLargeXmlResOp() {
-            super("ParseLargeXmlRes", "Parse large XML resource");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            SimpleInflater inf = new SimpleInflater(mContext);
-            inf.inflate(R.xml.simple_large);
-            return true;
-        }
-    }
-
-    static class LayoutInflaterOp extends Op {
-        Context mContext;
-
-        LayoutInflaterOp() {
-            super("LayoutInflater", "Inflate layout resource");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
-            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            inf.inflate(R.layout.small_layout, null);
-            return true;
-        }
-    }
-
-    static class LayoutInflaterLargeOp extends Op {
-        Context mContext;
-
-        LayoutInflaterLargeOp() {
-            super("LayoutInflaterLarge", "Inflate large layout resource");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
-            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            inf.inflate(R.layout.large_layout, null);
-            return true;
-        }
-    }
-
-    static class LayoutInflaterViewOp extends Op {
-        Context mContext;
-
-        LayoutInflaterViewOp() {
-            super("LayoutInflaterView", "Inflate layout with 50 View objects");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
-            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            inf.inflate(R.layout.view_layout, null);
-            return true;
-        }
-    }
-
-    static class LayoutInflaterButtonOp extends Op {
-        Context mContext;
-
-        LayoutInflaterButtonOp() {
-            super("LayoutInflaterButton", "Inflate layout with 50 Button objects");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
-            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            inf.inflate(R.layout.button_layout, null);
-            return true;
-        }
-    }
-
-    static class LayoutInflaterImageButtonOp extends Op {
-        Context mContext;
-
-        LayoutInflaterImageButtonOp() {
-            super("LayoutInflaterImageButton", "Inflate layout with 50 ImageButton objects");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
-            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            inf.inflate(R.layout.image_button_layout, null);
-            return true;
-        }
-    }
-
-    static class CreateBitmapOp extends Op {
-        Context mContext;
-
-        CreateBitmapOp() {
-            super("CreateBitmap", "Create a Bitmap");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
-            return true;
-        }
-    }
-
-    static class CreateRecycleBitmapOp extends Op {
-        Context mContext;
-
-        CreateRecycleBitmapOp() {
-            super("CreateRecycleBitmap", "Create and recycle a Bitmap");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
-            bm.recycle();
-            return true;
-        }
-    }
-
-    static class LoadSmallBitmapOp extends Op {
-        Context mContext;
-
-        LoadSmallBitmapOp() {
-            super("LoadSmallBitmap", "Load small raw bitmap");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.stat_sample, opts);
-            return true;
-        }
-    }
-
-    static class LoadRecycleSmallBitmapOp extends Op {
-        Context mContext;
-
-        LoadRecycleSmallBitmapOp() {
-            super("LoadRecycleSmallBitmap", "Load and recycle small raw bitmap");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.stat_sample, opts);
-            bm.recycle();
-            return true;
-        }
-    }
-
-    static class LoadLargeBitmapOp extends Op {
-        Context mContext;
-
-        LoadLargeBitmapOp() {
-            super("LoadLargeBitmap", "Load large raw bitmap");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.wallpaper_goldengate, opts);
-            return true;
-        }
-    }
-
-    static class LoadRecycleLargeBitmapOp extends Op {
-        Context mContext;
-
-        LoadRecycleLargeBitmapOp() {
-            super("LoadRecycleLargeBitmap", "Load and recycle large raw bitmap");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.wallpaper_goldengate, opts);
-            bm.recycle();
-            return true;
-        }
-    }
-
-    static class LoadSmallScaledBitmapOp extends Op {
-        Context mContext;
-
-        LoadSmallScaledBitmapOp() {
-            super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.stat_sample_scale, opts);
-            return true;
-        }
-    }
-
-    static class LoadLargeScaledBitmapOp extends Op {
-        Context mContext;
-
-        LoadLargeScaledBitmapOp() {
-            super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mContext = context;
-        }
-
-        boolean onRun() {
-            BitmapFactory.Options opts = new BitmapFactory.Options();
-            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
-            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
-                    R.drawable.wallpaper_goldengate_scale, opts);
-            return true;
-        }
-    }
-
-    static class CreateFileOp extends Op {
-        File mFile;
-
-        CreateFileOp() {
-            super("CreateFile", "Create and delete a file");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
-            mFile.delete();
-        }
-
-        boolean onRun() {
-            try {
-                mFile.createNewFile();
-            } catch (IOException e) {
-                Log.w(TAG, "Failure creating " + mFile, e);
-            }
-            mFile.delete();
-            return true;
-        }
-    }
-
-    static class CreateWriteFileOp extends Op {
-        File mFile;
-
-        CreateWriteFileOp() {
-            super("CreateWriteFile", "Create, write, and delete a file");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
-            mFile.delete();
-        }
-
-        boolean onRun() {
-            try {
-                FileOutputStream fos = new FileOutputStream(mFile);
-                fos.write(1);
-                fos.close();
-            } catch (IOException e) {
-                Log.w(TAG, "Failure creating " + mFile, e);
-            }
-            mFile.delete();
-            return true;
-        }
-    }
-
-    static class CreateWriteSyncFileOp extends Op {
-        File mFile;
-
-        CreateWriteSyncFileOp() {
-            super("CreateWriteSyncFile", "Create, write, sync, and delete a file");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
-            mFile.delete();
-        }
-
-        boolean onRun() {
-            try {
-                FileOutputStream fos = new FileOutputStream(mFile);
-                fos.write(1);
-                fos.flush();
-                FileUtils.sync(fos);
-                fos.close();
-            } catch (IOException e) {
-                Log.w(TAG, "Failure creating " + mFile, e);
-            }
-            mFile.delete();
-            return true;
-        }
-    }
-
-    static class WriteFileOp extends Op {
-        File mFile;
-        RandomAccessFile mRAF;
-        byte[] mBuffer;
-
-        WriteFileOp() {
-            super("WriteFile", "Truncate and write a 64k file");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mBuffer = new byte[1024*64];
-            for (int i=0; i<mBuffer.length; i++) {
-                mBuffer[i] = (byte)i;
-            }
-            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
-            mFile.delete();
-            try {
-                mRAF = new RandomAccessFile(mFile, "rw");
-            } catch (FileNotFoundException e) {
-                Log.w(TAG, "Failure creating " + mFile, e);
-            }
-        }
-
-        boolean onRun() {
-            try {
-                mRAF.seek(0);
-                mRAF.setLength(0);
-                mRAF.write(mBuffer);
-            } catch (IOException e) {
-                Log.w(TAG, "Failure writing " + mFile, e);
-            }
-            return true;
-        }
-
-        void onTerm(Context context) {
-            try {
-                mRAF.close();
-            } catch (IOException e) {
-                Log.w(TAG, "Failure closing " + mFile, e);
-            }
-            mFile.delete();
-        }
-    }
-
-    static class ReadFileOp extends Op {
-        File mFile;
-        RandomAccessFile mRAF;
-        byte[] mBuffer;
-
-        ReadFileOp() {
-            super("ReadFile", "Seek and read a 64k file");
-        }
-
-        void onInit(Context context, boolean foreground) {
-            mBuffer = new byte[1024*64];
-            for (int i=0; i<mBuffer.length; i++) {
-                mBuffer[i] = (byte)i;
-            }
-            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
-            mFile.delete();
-            try {
-                mRAF = new RandomAccessFile(mFile, "rw");
-                mRAF.seek(0);
-                mRAF.setLength(0);
-                mRAF.write(mBuffer);
-            } catch (IOException e) {
-                Log.w(TAG, "Failure creating " + mFile, e);
-            }
-        }
-
-        boolean onRun() {
-            try {
-                mRAF.seek(0);
-                mRAF.read(mBuffer);
-            } catch (IOException e) {
-                Log.w(TAG, "Failure reading " + mFile, e);
-            }
-            return true;
-        }
-
-        void onTerm(Context context) {
-            try {
-                mRAF.close();
-            } catch (IOException e) {
-                Log.w(TAG, "Failure closing " + mFile, e);
-            }
-            mFile.delete();
-        }
-    }
 }
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/LocalTestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/LocalTestService.java
new file mode 100644
index 0000000..09c6be8
--- /dev/null
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/LocalTestService.java
@@ -0,0 +1,6 @@
+package com.android.frameworkperf;
+
+public class LocalTestService extends TestService {
+    void terminate() {
+    }
+}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/RunResult.java b/tests/FrameworkPerf/src/com/android/frameworkperf/RunResult.java
new file mode 100644
index 0000000..d14e434
--- /dev/null
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/RunResult.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package com.android.frameworkperf;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class RunResult implements Parcelable {
+    final String name;
+    final String fgLongName;
+    final String bgLongName;
+    final long fgTime;
+    final long fgOps;
+    final long bgTime;
+    final long bgOps;
+
+    RunResult(TestService.TestRunner op) {
+        name = op.getName();
+        fgLongName = op.getForegroundLongName();
+        bgLongName = op.getBackgroundLongName();
+        fgTime = op.getForegroundTime();
+        fgOps = op.getForegroundOps();
+        bgTime = op.getBackgroundTime();
+        bgOps = op.getBackgroundOps();
+    }
+
+    RunResult(Parcel source) {
+        name = source.readString();
+        fgLongName = source.readString();
+        bgLongName = source.readString();
+        fgTime = source.readLong();
+        fgOps = source.readLong();
+        bgTime = source.readLong();
+        bgOps = source.readLong();
+    }
+
+    float getFgMsPerOp() {
+        return fgOps != 0 ? (fgTime / (float)fgOps) : 0;
+    }
+
+    float getBgMsPerOp() {
+        return bgOps != 0 ? (bgTime / (float)bgOps) : 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(name);
+        dest.writeString(fgLongName);
+        dest.writeString(bgLongName);
+        dest.writeLong(fgTime);
+        dest.writeLong(fgOps);
+        dest.writeLong(bgTime);
+        dest.writeLong(bgOps);
+    }
+
+    public static final Parcelable.Creator<RunResult> CREATOR
+            = new Parcelable.Creator<RunResult>() {
+        public RunResult createFromParcel(Parcel in) {
+            return new RunResult(in);
+        }
+
+        public RunResult[] newArray(int size) {
+            return new RunResult[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
new file mode 100644
index 0000000..f2f7c56
--- /dev/null
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestArgs.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package com.android.frameworkperf;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class TestArgs implements Parcelable {
+    long maxTime;
+    int combOp = -1;
+    int fgOp = -1;
+    int bgOp = -1;
+
+    public TestArgs() {
+    }
+
+    public TestArgs(Parcel source) {
+        maxTime = source.readLong();
+        combOp = source.readInt();
+        fgOp = source.readInt();
+        bgOp = source.readInt();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(maxTime);
+        dest.writeInt(combOp);
+        dest.writeInt(fgOp);
+        dest.writeInt(bgOp);
+    }
+
+    public static final Parcelable.Creator<TestArgs> CREATOR
+            = new Parcelable.Creator<TestArgs>() {
+        public TestArgs createFromParcel(Parcel in) {
+            return new TestArgs(in);
+        }
+
+        public TestArgs[] newArray(int size) {
+            return new TestArgs[size];
+        }
+    };
+}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
new file mode 100644
index 0000000..3d939bd
--- /dev/null
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/TestService.java
@@ -0,0 +1,1054 @@
+/*
+ * 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.
+ */
+
+package com.android.frameworkperf;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.os.FileUtils;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Xml;
+import android.view.LayoutInflater;
+
+public class TestService extends Service {
+    static final String TAG = "Perf";
+
+    final static Op[] mOpPairs = new Op[] {
+            new MethodCallOp(), new NoOp(),
+            new MethodCallOp(), new CpuOp(),
+            new MethodCallOp(), new SchedulerOp(),
+            new MethodCallOp(), new GcOp(),
+            new MethodCallOp(), new CreateFileOp(),
+            new MethodCallOp(), new CreateWriteFileOp(),
+            new MethodCallOp(), new CreateWriteSyncFileOp(),
+            new MethodCallOp(), new WriteFileOp(),
+            new MethodCallOp(), new ReadFileOp(),
+            new SchedulerOp(), new SchedulerOp(),
+            new GcOp(), new NoOp(),
+            new IpcOp(), new NoOp(),
+            new IpcOp(), new CpuOp(),
+            new IpcOp(), new SchedulerOp(),
+            new IpcOp(), new GcOp(),
+            new IpcOp(), new CreateFileOp(),
+            new IpcOp(), new CreateWriteFileOp(),
+            new IpcOp(), new CreateWriteSyncFileOp(),
+            new IpcOp(), new WriteFileOp(),
+            new IpcOp(), new ReadFileOp(),
+            new CreateFileOp(), new NoOp(),
+            new CreateWriteFileOp(), new NoOp(),
+            new CreateWriteSyncFileOp(), new NoOp(),
+            new WriteFileOp(), new NoOp(),
+            new ReadFileOp(), new NoOp(),
+            new WriteFileOp(), new CreateWriteFileOp(),
+            new ReadFileOp(), new CreateWriteFileOp(),
+            new WriteFileOp(), new CreateWriteSyncFileOp(),
+            new ReadFileOp(), new CreateWriteSyncFileOp(),
+            new WriteFileOp(), new WriteFileOp(),
+            new WriteFileOp(), new ReadFileOp(),
+            new ReadFileOp(), new WriteFileOp(),
+            new ReadFileOp(), new ReadFileOp(),
+            new OpenXmlResOp(), new NoOp(),
+            new ReadXmlAttrsOp(), new NoOp(),
+            new ParseXmlResOp(), new NoOp(),
+            new ParseLargeXmlResOp(), new NoOp(),
+            new LayoutInflaterOp(), new NoOp(),
+            new LayoutInflaterLargeOp(), new NoOp(),
+            new LayoutInflaterViewOp(), new NoOp(),
+            new LayoutInflaterButtonOp(), new NoOp(),
+            new LayoutInflaterImageButtonOp(), new NoOp(),
+            new CreateBitmapOp(), new NoOp(),
+            new CreateRecycleBitmapOp(), new NoOp(),
+            new LoadSmallBitmapOp(), new NoOp(),
+            new LoadRecycleSmallBitmapOp(), new NoOp(),
+            new LoadLargeBitmapOp(), new NoOp(),
+            new LoadRecycleLargeBitmapOp(), new NoOp(),
+            new LoadSmallScaledBitmapOp(), new NoOp(),
+            new LoadLargeScaledBitmapOp(), new NoOp(),
+    };
+
+    final static Op[] mAvailOps = new Op[] {
+            null,
+            new NoOp(),
+            new CpuOp(),
+            new SchedulerOp(),
+            new MethodCallOp(),
+            new IpcOp(),
+            new CreateFileOp(),
+            new CreateWriteFileOp(),
+            new CreateWriteSyncFileOp(),
+            new WriteFileOp(),
+            new ReadFileOp(),
+            new OpenXmlResOp(),
+            new ReadXmlAttrsOp(),
+            new ParseXmlResOp(),
+            new ParseLargeXmlResOp(),
+            new LayoutInflaterOp(),
+            new LayoutInflaterLargeOp(),
+            new LayoutInflaterViewOp(),
+            new LayoutInflaterButtonOp(),
+            new LayoutInflaterImageButtonOp(),
+            new CreateBitmapOp(),
+            new CreateRecycleBitmapOp(),
+            new LoadSmallBitmapOp(),
+            new LoadRecycleSmallBitmapOp(),
+            new LoadLargeBitmapOp(),
+            new LoadRecycleLargeBitmapOp(),
+            new LoadSmallScaledBitmapOp(),
+            new LoadLargeScaledBitmapOp(),
+    };
+
+    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;
+
+    final Handler mHandler = new Handler() {
+        @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");
+                    final Messenger replyTo = msg.replyTo;
+                    mRunner.run(this, args, new Runnable() {
+                        @Override public void run() {
+                            if (replyTo != null) {
+                                Message msg = Message.obtain(null, RES_TEST_FINISHED);
+                                Bundle bundle = new Bundle();
+                                bundle.putParcelable("res", new RunResult(mRunner));
+                                msg.obj = bundle;
+                                try {
+                                    replyTo.send(msg);
+                                } catch (RemoteException e) {
+                                }
+                            }
+                        }
+                    });
+                } 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 {
+                            msg.replyTo.send(reply);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    terminate();
+                } break;
+            }
+        }
+    };
+
+    final TestRunner mRunner = new TestRunner();
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return (new Messenger(mHandler)).getBinder();
+    }
+
+    void terminate() {
+        Runtime.getRuntime().exit(0);
+    }
+
+    enum BackgroundMode {
+        NOTHING,
+        CPU,
+        SCHEDULER
+    };
+
+    public class TestRunner {
+        Handler mHandler;
+        long mMaxRunTime;
+        Op mForegroundOp;
+        Op mBackgroundOp;
+        Runnable mDoneCallback;
+
+        RunnerThread mBackgroundThread;
+        RunnerThread mForegroundThread;
+        long mStartTime;
+
+        boolean mBackgroundRunning;
+        boolean mForegroundRunning;
+
+        long mBackgroundEndTime;
+        long mBackgroundOps;
+        long mForegroundEndTime;
+        long mForegroundOps;
+
+        public TestRunner() {
+        }
+
+        public String getForegroundName() {
+            return mForegroundOp.getName();
+        }
+
+        public String getBackgroundName() {
+            return mBackgroundOp.getName();
+        }
+
+        public String getName() {
+            String fgName = mForegroundOp.getName();
+            String bgName = mBackgroundOp.getName();
+            StringBuilder res = new StringBuilder();
+            if (fgName != null) {
+                res.append(fgName);
+                res.append("Fg");
+            }
+            if (bgName != null) {
+                res.append(bgName);
+                res.append("Bg");
+            }
+            return res.toString();
+        }
+
+        public String getForegroundLongName() {
+            return mForegroundOp.getLongName();
+        }
+
+        public String getBackgroundLongName() {
+            return mBackgroundOp.getLongName();
+        }
+
+        public void run(Handler handler, TestArgs args, Runnable doneCallback) {
+            mHandler = handler;
+            mMaxRunTime = args.maxTime;
+            if (args.combOp >= 0) {
+                mForegroundOp = mOpPairs[args.combOp];
+                mBackgroundOp = mOpPairs[args.combOp+1];
+            } else {
+                mForegroundOp = mAvailOps[args.fgOp];
+                mBackgroundOp = mAvailOps[args.bgOp];
+            }
+            mDoneCallback = doneCallback;
+            mBackgroundThread = new RunnerThread("background", new Runnable() {
+                @Override public void run() {
+                    boolean running;
+                    int ops = 0;
+                    do {
+                        running = mBackgroundOp.onRun();
+                        ops++;
+                    } while (evalRepeat(running, true) && running);
+                    mBackgroundEndTime = SystemClock.uptimeMillis();
+                    mBackgroundOps = ops * mBackgroundOp.getOpsPerRun();
+                    threadFinished(false);
+                }
+            }, Process.THREAD_PRIORITY_BACKGROUND);
+            mForegroundThread = new RunnerThread("background", new Runnable() {
+                @Override public void run() {
+                    boolean running;
+                    int ops = 0;
+                    do {
+                        running = mForegroundOp.onRun();
+                        ops++;
+                    } while (evalRepeat(true, running) && running);
+                    mForegroundEndTime = SystemClock.uptimeMillis();
+                    mForegroundOps = ops * mForegroundOp.getOpsPerRun();
+                    threadFinished(true);
+                }
+            }, Process.THREAD_PRIORITY_FOREGROUND);
+
+            mForegroundOp.onInit(TestService.this, true);
+            mBackgroundOp.onInit(TestService.this, false);
+
+            synchronized (this) {
+                mStartTime = SystemClock.uptimeMillis();
+                mBackgroundRunning = true;
+                mForegroundRunning = true;
+            }
+
+            mBackgroundThread.start();
+            mForegroundThread.start();
+        }
+
+        public long getForegroundTime() {
+            return mForegroundEndTime-mStartTime;
+        }
+
+        public long getForegroundOps() {
+            return mForegroundOps;
+        }
+
+        public long getBackgroundTime() {
+            return mBackgroundEndTime-mStartTime;
+        }
+
+        public long getBackgroundOps() {
+            return mBackgroundOps;
+        }
+
+        private boolean evalRepeat(boolean bgRunning, boolean fgRunning) {
+            synchronized (this) {
+                if (!bgRunning) {
+                    mBackgroundRunning = false;
+                }
+                if (!fgRunning) {
+                    mForegroundRunning = false;
+                }
+                if (!mBackgroundRunning && !mForegroundRunning) {
+                    return false;
+                }
+                long now = SystemClock.uptimeMillis();
+                if (now > (mStartTime+mMaxRunTime)) {
+                    return false;
+                }
+                return true;
+            }
+        }
+
+        private void threadFinished(boolean foreground) {
+            synchronized (this) {
+                if (foreground) {
+                    mForegroundRunning = false;
+                } else {
+                    mBackgroundRunning = false;
+                }
+                if (!mBackgroundRunning && !mForegroundRunning) {
+                    mHandler.post(new Runnable() {
+                        @Override public void run() {
+                            mForegroundOp.onTerm(TestService.this);
+                            mBackgroundOp.onTerm(TestService.this);
+                            if (mDoneCallback != null) {
+                                mDoneCallback.run();
+                            }
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    class RunnerThread extends Thread {
+        private final Runnable mOp;
+        private final int mPriority;
+
+        RunnerThread(String name, Runnable op, int priority) {
+            super(name);
+            mOp = op;
+            mPriority = priority;
+        }
+
+        public void run() {
+            Process.setThreadPriority(mPriority);
+            mOp.run();
+        }
+    }
+
+    static public abstract class Op {
+        final String mName;
+        final String mLongName;
+
+        public Op(String name, String longName) {
+            mName = name;
+            mLongName = longName;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public String getLongName() {
+            return mLongName;
+        }
+
+        void onInit(Context context, boolean foreground) {
+        }
+
+        abstract boolean onRun();
+
+        void onTerm(Context context) {
+        }
+
+        int getOpsPerRun() {
+            return 1;
+        }
+    }
+
+    static class NoOp extends Op {
+        NoOp() {
+            super(null, "Nothing");
+        }
+
+        boolean onRun() {
+            return false;
+        }
+
+        int getOpsPerRun() {
+            return 0;
+        }
+    }
+
+    static class CpuOp extends Op {
+        CpuOp() {
+            super("CPU", "Consume CPU");
+        }
+
+        boolean onRun() {
+            return true;
+        }
+    }
+
+    static class SchedulerOp extends Op {
+        SchedulerOp() {
+            super("Sched", "Change scheduler group");
+        }
+
+        boolean onRun() {
+            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+            return true;
+        }
+    }
+
+    static class GcOp extends Op {
+        GcOp() {
+            super("Gc", "Run garbage collector");
+        }
+
+        boolean onRun() {
+            byte[] stuff = new byte[1024*1024];
+            return true;
+        }
+    }
+
+    static class MethodCallOp extends Op {
+        MethodCallOp() {
+            super("MethodCall", "Method call");
+        }
+
+        boolean onRun() {
+            final int N = getOpsPerRun();
+            for (int i=0; i<N; i++) {
+                someFunc(i);
+            }
+            return true;
+        }
+
+        int someFunc(int foo) {
+            return 0;
+        }
+
+        int getOpsPerRun() {
+            return 500;
+        }
+    }
+
+    static class IpcOp extends Op {
+        PackageManager mPm;
+        String mProcessName;
+
+        IpcOp() {
+            super("Ipc", "IPC to system process");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mPm = context.getPackageManager();
+            mProcessName = context.getApplicationInfo().processName;
+        }
+
+        boolean onRun() {
+            final int N = getOpsPerRun();
+            for (int i=0; i<N; i++) {
+                mPm.queryContentProviders(mProcessName, Process.myUid(), 0);
+            }
+            return true;
+        }
+
+        int getOpsPerRun() {
+            return 100;
+        }
+    }
+
+    static class OpenXmlResOp extends Op {
+        Context mContext;
+
+        OpenXmlResOp() {
+            super("OpenXmlRes", "Open (and close) an XML resource");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            XmlResourceParser parser = mContext.getResources().getLayout(R.xml.simple);
+            parser.close();
+            return true;
+        }
+    }
+
+    static class ReadXmlAttrsOp extends Op {
+        Context mContext;
+        XmlResourceParser mParser;
+        AttributeSet mAttrs;
+
+        ReadXmlAttrsOp() {
+            super("ReadXmlAttrs", "Read attributes from an XML tag");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+            mParser = mContext.getResources().getLayout(R.xml.simple);
+            mAttrs = Xml.asAttributeSet(mParser);
+
+            int eventType;
+            try {
+                // Find the first <item> tag.
+                eventType = mParser.getEventType();
+                String tagName;
+                do {
+                    if (eventType == XmlPullParser.START_TAG) {
+                        tagName = mParser.getName();
+                        if (tagName.equals("item")) {
+                            break;
+                        }
+                    }
+                    eventType = mParser.next();
+                } while (eventType != XmlPullParser.END_DOCUMENT);
+            } catch (XmlPullParserException e) {
+                throw new RuntimeException("I died", e);
+            } catch (IOException e) {
+                throw new RuntimeException("I died", e);
+            }
+        }
+
+        void onTerm(Context context) {
+            mParser.close();
+        }
+
+        boolean onRun() {
+            TypedArray a = mContext.obtainStyledAttributes(mAttrs,
+                    com.android.internal.R.styleable.MenuItem);
+            a.recycle();
+            return true;
+        }
+    }
+
+    static class ParseXmlResOp extends Op {
+        Context mContext;
+
+        ParseXmlResOp() {
+            super("ParseXmlRes", "Parse compiled XML resource");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            SimpleInflater inf = new SimpleInflater(mContext);
+            inf.inflate(R.xml.simple);
+            return true;
+        }
+    }
+
+    static class ParseLargeXmlResOp extends Op {
+        Context mContext;
+
+        ParseLargeXmlResOp() {
+            super("ParseLargeXmlRes", "Parse large XML resource");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            SimpleInflater inf = new SimpleInflater(mContext);
+            inf.inflate(R.xml.simple_large);
+            return true;
+        }
+    }
+
+    static class LayoutInflaterOp extends Op {
+        Context mContext;
+
+        LayoutInflaterOp() {
+            super("LayoutInflater", "Inflate layout resource");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            if (Looper.myLooper() == null) {
+                Looper.prepare();
+            }
+            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            inf.inflate(R.layout.small_layout, null);
+            return true;
+        }
+    }
+
+    static class LayoutInflaterLargeOp extends Op {
+        Context mContext;
+
+        LayoutInflaterLargeOp() {
+            super("LayoutInflaterLarge", "Inflate large layout resource");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            if (Looper.myLooper() == null) {
+                Looper.prepare();
+            }
+            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            inf.inflate(R.layout.large_layout, null);
+            return true;
+        }
+    }
+
+    static class LayoutInflaterViewOp extends Op {
+        Context mContext;
+
+        LayoutInflaterViewOp() {
+            super("LayoutInflaterView", "Inflate layout with 50 View objects");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            if (Looper.myLooper() == null) {
+                Looper.prepare();
+            }
+            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            inf.inflate(R.layout.view_layout, null);
+            return true;
+        }
+    }
+
+    static class LayoutInflaterButtonOp extends Op {
+        Context mContext;
+
+        LayoutInflaterButtonOp() {
+            super("LayoutInflaterButton", "Inflate layout with 50 Button objects");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            if (Looper.myLooper() == null) {
+                Looper.prepare();
+            }
+            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            inf.inflate(R.layout.button_layout, null);
+            return true;
+        }
+    }
+
+    static class LayoutInflaterImageButtonOp extends Op {
+        Context mContext;
+
+        LayoutInflaterImageButtonOp() {
+            super("LayoutInflaterImageButton", "Inflate layout with 50 ImageButton objects");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            if (Looper.myLooper() == null) {
+                Looper.prepare();
+            }
+            LayoutInflater inf = (LayoutInflater)mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            inf.inflate(R.layout.image_button_layout, null);
+            return true;
+        }
+    }
+
+    static class CreateBitmapOp extends Op {
+        Context mContext;
+
+        CreateBitmapOp() {
+            super("CreateBitmap", "Create a Bitmap");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
+            return true;
+        }
+    }
+
+    static class CreateRecycleBitmapOp extends Op {
+        Context mContext;
+
+        CreateRecycleBitmapOp() {
+            super("CreateRecycleBitmap", "Create and recycle a Bitmap");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
+            bm.recycle();
+            return true;
+        }
+    }
+
+    static class LoadSmallBitmapOp extends Op {
+        Context mContext;
+
+        LoadSmallBitmapOp() {
+            super("LoadSmallBitmap", "Load small raw bitmap");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.stat_sample, opts);
+            return true;
+        }
+    }
+
+    static class LoadRecycleSmallBitmapOp extends Op {
+        Context mContext;
+
+        LoadRecycleSmallBitmapOp() {
+            super("LoadRecycleSmallBitmap", "Load and recycle small raw bitmap");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.stat_sample, opts);
+            bm.recycle();
+            return true;
+        }
+    }
+
+    static class LoadLargeBitmapOp extends Op {
+        Context mContext;
+
+        LoadLargeBitmapOp() {
+            super("LoadLargeBitmap", "Load large raw bitmap");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.wallpaper_goldengate, opts);
+            return true;
+        }
+    }
+
+    static class LoadRecycleLargeBitmapOp extends Op {
+        Context mContext;
+
+        LoadRecycleLargeBitmapOp() {
+            super("LoadRecycleLargeBitmap", "Load and recycle large raw bitmap");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.wallpaper_goldengate, opts);
+            bm.recycle();
+            return true;
+        }
+    }
+
+    static class LoadSmallScaledBitmapOp extends Op {
+        Context mContext;
+
+        LoadSmallScaledBitmapOp() {
+            super("LoadSmallScaledBitmap", "Load small raw bitmap that is scaled for density");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.stat_sample_scale, opts);
+            return true;
+        }
+    }
+
+    static class LoadLargeScaledBitmapOp extends Op {
+        Context mContext;
+
+        LoadLargeScaledBitmapOp() {
+            super("LoadLargeScaledBitmap", "Load large raw bitmap that is scaled for density");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mContext = context;
+        }
+
+        boolean onRun() {
+            BitmapFactory.Options opts = new BitmapFactory.Options();
+            opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+            Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.wallpaper_goldengate_scale, opts);
+            return true;
+        }
+    }
+
+    static class CreateFileOp extends Op {
+        File mFile;
+
+        CreateFileOp() {
+            super("CreateFile", "Create and delete a file");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
+            mFile.delete();
+        }
+
+        boolean onRun() {
+            try {
+                mFile.createNewFile();
+            } catch (IOException e) {
+                Log.w(TAG, "Failure creating " + mFile, e);
+            }
+            mFile.delete();
+            return true;
+        }
+    }
+
+    static class CreateWriteFileOp extends Op {
+        File mFile;
+
+        CreateWriteFileOp() {
+            super("CreateWriteFile", "Create, write, and delete a file");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
+            mFile.delete();
+        }
+
+        boolean onRun() {
+            try {
+                FileOutputStream fos = new FileOutputStream(mFile);
+                fos.write(1);
+                fos.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Failure creating " + mFile, e);
+            }
+            mFile.delete();
+            return true;
+        }
+    }
+
+    static class CreateWriteSyncFileOp extends Op {
+        File mFile;
+
+        CreateWriteSyncFileOp() {
+            super("CreateWriteSyncFile", "Create, write, sync, and delete a file");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
+            mFile.delete();
+        }
+
+        boolean onRun() {
+            try {
+                FileOutputStream fos = new FileOutputStream(mFile);
+                fos.write(1);
+                fos.flush();
+                FileUtils.sync(fos);
+                fos.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Failure creating " + mFile, e);
+            }
+            mFile.delete();
+            return true;
+        }
+    }
+
+    static class WriteFileOp extends Op {
+        File mFile;
+        RandomAccessFile mRAF;
+        byte[] mBuffer;
+
+        WriteFileOp() {
+            super("WriteFile", "Truncate and write a 64k file");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mBuffer = new byte[1024*64];
+            for (int i=0; i<mBuffer.length; i++) {
+                mBuffer[i] = (byte)i;
+            }
+            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
+            mFile.delete();
+            try {
+                mRAF = new RandomAccessFile(mFile, "rw");
+            } catch (FileNotFoundException e) {
+                Log.w(TAG, "Failure creating " + mFile, e);
+            }
+        }
+
+        boolean onRun() {
+            try {
+                mRAF.seek(0);
+                mRAF.setLength(0);
+                mRAF.write(mBuffer);
+            } catch (IOException e) {
+                Log.w(TAG, "Failure writing " + mFile, e);
+            }
+            return true;
+        }
+
+        void onTerm(Context context) {
+            try {
+                mRAF.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Failure closing " + mFile, e);
+            }
+            mFile.delete();
+        }
+    }
+
+    static class ReadFileOp extends Op {
+        File mFile;
+        RandomAccessFile mRAF;
+        byte[] mBuffer;
+
+        ReadFileOp() {
+            super("ReadFile", "Seek and read a 64k file");
+        }
+
+        void onInit(Context context, boolean foreground) {
+            mBuffer = new byte[1024*64];
+            for (int i=0; i<mBuffer.length; i++) {
+                mBuffer[i] = (byte)i;
+            }
+            mFile = context.getFileStreamPath(foreground ? "test-fg.file" : "test-bg.file");
+            mFile.delete();
+            try {
+                mRAF = new RandomAccessFile(mFile, "rw");
+                mRAF.seek(0);
+                mRAF.setLength(0);
+                mRAF.write(mBuffer);
+            } catch (IOException e) {
+                Log.w(TAG, "Failure creating " + mFile, e);
+            }
+        }
+
+        boolean onRun() {
+            try {
+                mRAF.seek(0);
+                mRAF.read(mBuffer);
+            } catch (IOException e) {
+                Log.w(TAG, "Failure reading " + mFile, e);
+            }
+            return true;
+        }
+
+        void onTerm(Context context) {
+            try {
+                mRAF.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Failure closing " + mFile, e);
+            }
+            mFile.delete();
+        }
+    }
+}
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 e981da7..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;
@@ -211,7 +212,7 @@
     static final int CMD_STOP_SUPPLICANT                  = BASE + 12;
     /* Start the driver */
     static final int CMD_START_DRIVER                     = BASE + 13;
-    /* Start the driver */
+    /* Stop the driver */
     static final int CMD_STOP_DRIVER                      = BASE + 14;
     /* Indicates Static IP succeded */
     static final int CMD_STATIC_IP_SUCCESS                = BASE + 15;
@@ -219,6 +220,9 @@
     static final int CMD_STATIC_IP_FAILURE                = BASE + 16;
     /* Indicates supplicant stop failed */
     static final int CMD_STOP_SUPPLICANT_FAILED           = BASE + 17;
+    /* Delayed stop to avoid shutting down driver too quick*/
+    static final int CMD_DELAYED_STOP_DRIVER              = BASE + 18;
+
 
     /* Start the soft access point */
     static final int CMD_START_AP                         = BASE + 21;
@@ -230,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 ? */
@@ -389,6 +397,13 @@
     private static final int MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS = 10 * 60 * 1000; /* 10 minutes */
     private long mLastEnableAllNetworksTime;
 
+    /**
+     * Starting and shutting down driver too quick causes problems leading to driver
+     * being in a bad state. Delay driver stop.
+     */
+    private static final int DELAYED_DRIVER_STOP_MS = 2 * 60 * 1000; /* 2 minutes */
+    private int mDelayedStopCounter;
+    private boolean mInDelayedStop = false;
 
     private static final int MIN_RSSI = -200;
     private static final int MAX_RSSI = 256;
@@ -520,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;
@@ -649,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;
@@ -1651,6 +1671,7 @@
             mDhcpInfoInternal = dhcpInfoInternal;
         }
         mLastSignalLevel = -1; // force update of signal strength
+        mReconnectCount = 0; //Reset IP failure tracking
         WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal);
         InetAddress addr = NetworkUtils.numericToInetAddress(dhcpInfoInternal.ipAddress);
         mWifiInfo.setInetAddress(addr);
@@ -1703,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();
     }
 
     /********************************************************
@@ -1764,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:
@@ -1779,6 +1795,7 @@
                 case CMD_STOP_SUPPLICANT_FAILED:
                 case CMD_START_DRIVER:
                 case CMD_STOP_DRIVER:
+                case CMD_DELAYED_STOP_DRIVER:
                 case CMD_START_AP:
                 case CMD_START_AP_SUCCESS:
                 case CMD_START_AP_FAILURE:
@@ -1811,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);
@@ -1844,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);
             }
@@ -2441,6 +2461,7 @@
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
             mIsRunning = true;
+            mInDelayedStop = false;
             updateBatteryWorkSource(null);
 
             /**
@@ -2520,6 +2541,30 @@
                     WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive);
                     break;
                 case CMD_STOP_DRIVER:
+                    /* Already doing a delayed stop */
+                    if (mInDelayedStop) {
+                        if (DBG) log("Already in delayed stop");
+                        break;
+                    }
+                    mInDelayedStop = true;
+                    mDelayedStopCounter++;
+                    if (DBG) log("Delayed stop message " + mDelayedStopCounter);
+                    sendMessageDelayed(obtainMessage(CMD_DELAYED_STOP_DRIVER, mDelayedStopCounter,
+                            0), DELAYED_DRIVER_STOP_MS);
+                    break;
+                case CMD_START_DRIVER:
+                    if (mInDelayedStop) {
+                        mInDelayedStop = false;
+                        mDelayedStopCounter++;
+                        if (DBG) log("Delayed stop ignored due to start");
+                    }
+                    break;
+                case CMD_DELAYED_STOP_DRIVER:
+                    if (message.arg1 != mDelayedStopCounter) break;
+                    if (getCurrentState() != mDisconnectedState) {
+                        WifiNative.disconnectCommand();
+                        handleNetworkDisconnect();
+                    }
                     mWakeLock.acquire();
                     WifiNative.stopDriverCommand();
                     transitionTo(mDriverStoppingState);
@@ -2878,10 +2923,6 @@
                   /* Ignore */
               case WifiMonitor.NETWORK_CONNECTION_EVENT:
                   break;
-              case CMD_STOP_DRIVER:
-                  sendMessage(CMD_DISCONNECT);
-                  deferMessage(message);
-                  break;
               case CMD_SET_SCAN_MODE:
                   if (message.arg1 == SCAN_ONLY_MODE) {
                       sendMessage(CMD_DISCONNECT);
@@ -2936,10 +2977,6 @@
                     WifiNative.disconnectCommand();
                     transitionTo(mDisconnectingState);
                     break;
-                case CMD_STOP_DRIVER:
-                    sendMessage(CMD_DISCONNECT);
-                    deferMessage(message);
-                    break;
                 case CMD_REQUEST_CM_WAKELOCK:
                     checkAndSetConnectivityInstance();
                     mCm.requestNetworkTransitionWakelock(TAG);
@@ -3035,9 +3072,6 @@
         public boolean processMessage(Message message) {
             if (DBG) log(getName() + message.toString() + "\n");
             switch (message.what) {
-                case CMD_STOP_DRIVER: /* Stop driver only after disconnect handled */
-                    deferMessage(message);
-                    break;
                 case CMD_SET_SCAN_MODE:
                     if (message.arg1 == SCAN_ONLY_MODE) {
                         deferMessage(message);
@@ -3217,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) {
@@ -3256,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);