Merge change 26379 into eclair

* changes:
  Add parameter for the restore set (device id) data is being restored from to the restore_start event
diff --git a/api/current.xml b/api/current.xml
index 15bc2fa..fa54a10 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2825,6 +2825,28 @@
  visibility="public"
 >
 </field>
+<field name="detailColumn"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843427"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="detailSocialSummary"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843428"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dial"
  type="int"
  transient="false"
@@ -7522,6 +7544,17 @@
  visibility="public"
 >
 </field>
+<field name="summaryColumn"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843426"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="summaryOff"
  type="int"
  transient="false"
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index caf72af..a2c95f4 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1144,7 +1144,7 @@
         String query = mSearchAutoComplete.getText().toString();
         String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH;
         Intent intent = createIntent(action, null, null, query, null,
-                actionKey, actionMsg);
+                actionKey, actionMsg, null);
         // Allow GlobalSearch to log and create shortcut for searches launched by
         // the search button, enter key or an action key.
         if (mGlobalSearchMode) {
@@ -1579,9 +1579,10 @@
 
             String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY);
             String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
+            String mode = mGlobalSearchMode ? SearchManager.MODE_GLOBAL_SEARCH_SUGGESTION : null;
 
             return createIntent(action, dataUri, extraData, query, componentName, actionKey,
-                    actionMsg);
+                    actionMsg, mode);
         } catch (RuntimeException e ) {
             int rowNum;
             try {                       // be really paranoid now
@@ -1607,13 +1608,18 @@
      *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
      * @param actionMsg The message for the action key that was pressed,
      *        or <code>null</code> if none.
+     * @param mode The search mode, one of the acceptable values for
+     *             {@link SearchManager#SEARCH_MODE}, or {@code null}.
      * @return The intent.
      */
     private Intent createIntent(String action, Uri data, String extraData, String query,
-            String componentName, int actionKey, String actionMsg) {
+            String componentName, int actionKey, String actionMsg, String mode) {
         // Now build the Intent
         Intent intent = new Intent(action);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        // We need CLEAR_TOP to avoid reusing an old task that has other activities
+        // on top of the one we want.
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
         if (data != null) {
             intent.setData(data);
         }
@@ -1634,6 +1640,9 @@
             intent.putExtra(SearchManager.ACTION_KEY, actionKey);
             intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
         }
+        if (mode != null) {
+            intent.putExtra(SearchManager.SEARCH_MODE, mode);
+        }
         // Only allow 3rd-party intents from GlobalSearch
         if (!mGlobalSearchMode) {
             intent.setComponent(mSearchable.getSearchActivity());
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 6a0285d..f0876f4 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1289,6 +1289,25 @@
     public final static String SOURCE = "source";
 
     /**
+     * Intent extra data key: Use {@link android.content.Intent#getBundleExtra
+     * content.Intent.getBundleExtra(SEARCH_MODE)} to get the search mode used
+     * to launch the intent.
+     * The only current value for this is {@link #MODE_GLOBAL_SEARCH_SUGGESTION}.
+     *
+     * @hide
+     */
+    public final static String SEARCH_MODE = "search_mode";
+
+    /**
+     * Value for the {@link #SEARCH_MODE} key.
+     * This is used if the intent was launched by clicking a suggestion in global search
+     * mode (Quick Search Box).
+     *
+     * @hide
+     */
+    public static final String MODE_GLOBAL_SEARCH_SUGGESTION = "global_search_suggestion";
+
+    /**
      * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
      * {@link android.content.Intent#getIntExtra content.Intent.getIntExtra()}
      * to obtain the keycode that the user used to trigger this query.  It will be zero if the
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 50faf57..11c67cc 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -274,6 +274,25 @@
          * Apply translation to the canvas that is necessary to draw the content.
          */
         public void translateCanvas(Canvas canvas) {
+            if (applicationScale == 1.5f) {
+                /*  When we scale for compatibility, we can put our stretched
+                    bitmaps and ninepatches on exacty 1/2 pixel boundaries,
+                    which can give us inconsistent drawing due to imperfect
+                    float precision in the graphics engine's inverse matrix.
+                 
+                    As a work-around, we translate by a tiny amount to avoid
+                    landing on exact pixel centers and boundaries, giving us
+                    the slop we need to draw consistently.
+                 
+                    This constant is meant to resolve to 1/255 after it is
+                    scaled by 1.5 (applicationScale). Note, this is just a guess
+                    as to what is small enough not to create its own artifacts,
+                    and big enough to avoid the precision problems. Feel free
+                    to experiment with smaller values as you choose.
+                 */
+                final float tinyOffset = 2.0f / (3 * 255);
+                canvas.translate(tinyOffset, tinyOffset);
+            }
             canvas.scale(applicationScale, applicationScale);
         }
 
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index dbddb2e..e233a02 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -605,8 +605,8 @@
     }
 
     // Called by JNI when an apple-touch-icon attribute was found.
-    private void didReceiveTouchIconUrl(String url) {
-        mCallbackProxy.onReceivedTouchIconUrl(url);
+    private void didReceiveTouchIconUrl(String url, boolean precomposed) {
+        mCallbackProxy.onReceivedTouchIconUrl(url, precomposed);
     }
 
     /**
@@ -707,6 +707,10 @@
         return value.string.toString();
     }
 
+    private float density() {
+        return mContext.getResources().getDisplayMetrics().density;
+    }
+
     //==========================================================================
     // native functions
     //==========================================================================
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index b051675..1ec769b 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -249,7 +249,7 @@
             case RECEIVED_TOUCH_ICON_URL:
                 if (mWebChromeClient != null) {
                     mWebChromeClient.onReceivedTouchIconUrl(mWebView,
-                            (String) msg.obj);
+                            (String) msg.obj, msg.arg1 == 1);
                 }
                 break;
 
@@ -1065,19 +1065,22 @@
         sendMessage(obtainMessage(RECEIVED_ICON, icon));
     }
 
-    /* package */ void onReceivedTouchIconUrl(String url) {
+    /* package */ void onReceivedTouchIconUrl(String url, boolean precomposed) {
         // We should have a current item but we do not want to crash so check
         // for null.
         WebHistoryItem i = mBackForwardList.getCurrentItem();
         if (i != null) {
-            i.setTouchIconUrl(url);
+            if (precomposed || i.getTouchIconUrl() != null) {
+                i.setTouchIconUrl(url);
+            }
         }
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
         if (mWebChromeClient == null) {
             return;
         }
-        sendMessage(obtainMessage(RECEIVED_TOUCH_ICON_URL, url));
+        sendMessage(obtainMessage(RECEIVED_TOUCH_ICON_URL,
+                precomposed ? 1 : 0, 0, url));
     }
 
     public void onReceivedTitle(String title) {
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index e985ccc..c0cac01 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -19,10 +19,9 @@
 import android.os.Handler;
 import android.os.Message;
 import android.util.Log;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 
@@ -47,15 +46,13 @@
     private static GeolocationPermissions sInstance;
 
     private Handler mHandler;
+    private Handler mUIHandler;
 
     // Members used to transfer the origins and permissions between threads.
     private Set<String> mOrigins;
     private boolean mAllowed;
     private Set<String> mOriginsToClear;
     private Set<String> mOriginsToAllow;
-    private static Lock mLock = new ReentrantLock();
-    private static boolean mUpdated;
-    private static Condition mUpdatedCondition = mLock.newCondition();
 
     // Message ids
     static final int GET_ORIGINS = 0;
@@ -64,6 +61,15 @@
     static final int ALLOW = 3;
     static final int CLEAR_ALL = 4;
 
+    // Message ids on the UI thread
+    static final int RETURN_ORIGINS = 0;
+    static final int RETURN_ALLOWED = 1;
+
+    private static final String ORIGINS = "origins";
+    private static final String ORIGIN = "origin";
+    private static final String CALLBACK = "callback";
+    private static final String ALLOWED = "allowed";
+
     /**
      * Gets the singleton instance of the class.
      */
@@ -75,22 +81,62 @@
     }
 
     /**
+     * Creates the UI message handler. Must be called on the UI thread.
+     */
+    public void createUIHandler() {
+        if (mUIHandler == null) {
+            mUIHandler = new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    // Runs on the UI thread.
+                    switch (msg.what) {
+                        case RETURN_ORIGINS: {
+                            Map values = (Map) msg.obj;
+                            Set origins = (Set) values.get(ORIGINS);
+                            ValueCallback<Set> callback = (ValueCallback<Set>) values.get(CALLBACK);
+                            callback.onReceiveValue(origins);
+                        } break;
+                        case RETURN_ALLOWED: {
+                            Map values = (Map) msg.obj;
+                            Boolean allowed = (Boolean) values.get(ALLOWED);
+                            ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK);
+                            callback.onReceiveValue(allowed);
+                        } break;
+                    }
+                }
+            };
+        }
+    }
+
+    /**
      * Creates the message handler. Must be called on the WebKit thread.
      */
     public void createHandler() {
-        mLock.lock();
         if (mHandler == null) {
             mHandler = new Handler() {
                 @Override
                 public void handleMessage(Message msg) {
                     // Runs on the WebKit thread.
                     switch (msg.what) {
-                        case GET_ORIGINS:
+                        case GET_ORIGINS: {
                             getOriginsImpl();
-                            break;
-                        case GET_ALLOWED:
-                            getAllowedImpl((String) msg.obj);
-                            break;
+                            ValueCallback callback = (ValueCallback) msg.obj;
+                            Set origins = new HashSet(mOrigins);
+                            Map values = new HashMap<String, Object>();
+                            values.put(CALLBACK, callback);
+                            values.put(ORIGINS, origins);
+                            postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
+                            } break;
+                        case GET_ALLOWED: {
+                            Map values = (Map) msg.obj;
+                            String origin = (String) values.get(ORIGIN);
+                            ValueCallback callback = (ValueCallback) values.get(CALLBACK);
+                            getAllowedImpl(origin);
+                            Map retValues = new HashMap<String, Object>();
+                            retValues.put(CALLBACK, callback);
+                            retValues.put(ALLOWED, new Boolean(mAllowed));
+                            postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
+                            } break;
                         case CLEAR:
                             nativeClear((String) msg.obj);
                             break;
@@ -115,7 +161,6 @@
                 }
             }
         }
-        mLock.unlock();
     }
 
     /**
@@ -127,29 +172,31 @@
     }
 
     /**
+     * Utility function to send a message to the handler on the UI thread
+     */
+    private void postUIMessage(Message msg) {
+        if (mUIHandler != null) {
+            mUIHandler.sendMessage(msg);
+        }
+    }
+
+    /**
      * Gets the set of origins for which Geolocation permissions are stored.
      * Note that we represent the origins as strings. These are created using
      * WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
      * (Database, Geolocation etc) do so, it's safe to match up origins for the
      * purposes of displaying UI.
      */
-    public Set getOrigins() {
-        // Called on the UI thread.
-        Set origins = null;
-        mLock.lock();
-        try {
-            mUpdated = false;
-            postMessage(Message.obtain(null, GET_ORIGINS));
-            while (!mUpdated) {
-                mUpdatedCondition.await();
+    public void getOrigins(ValueCallback<Set> callback) {
+        if (callback != null) {
+            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+                getOriginsImpl();
+                Set origins = new HashSet(mOrigins);
+                callback.onReceiveValue(origins);
+            } else {
+                postMessage(Message.obtain(null, GET_ORIGINS, callback));
             }
-            origins = mOrigins;
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Exception while waiting for update", e);
-        } finally {
-            mLock.unlock();
         }
-        return origins;
     }
 
     /**
@@ -157,33 +204,29 @@
      */
     private void getOriginsImpl() {
         // Called on the WebKit thread.
-        mLock.lock();
         mOrigins = nativeGetOrigins();
-        mUpdated = true;
-        mUpdatedCondition.signal();
-        mLock.unlock();
     }
 
     /**
      * Gets the permission state for the specified origin.
      */
-    public boolean getAllowed(String origin) {
-        // Called on the UI thread.
-        boolean allowed = false;
-        mLock.lock();
-        try {
-            mUpdated = false;
-            postMessage(Message.obtain(null, GET_ALLOWED, origin));
-            while (!mUpdated) {
-                mUpdatedCondition.await();
-            }
-            allowed = mAllowed;
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Exception while waiting for update", e);
-        } finally {
-            mLock.unlock();
+    public void getAllowed(String origin, ValueCallback<Boolean> callback) {
+        if (callback == null) {
+            return;
         }
-        return allowed;
+        if (origin == null) {
+            callback.onReceiveValue(null);
+            return;
+        }
+        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+            getAllowedImpl(origin);
+            callback.onReceiveValue(new Boolean(mAllowed));
+        } else {
+            Map values = new HashMap<String, Object>();
+            values.put(ORIGIN, origin);
+            values.put(CALLBACK, callback);
+            postMessage(Message.obtain(null, GET_ALLOWED, values));
+        }
     }
 
     /**
@@ -191,11 +234,7 @@
      */
     private void getAllowedImpl(String origin) {
         // Called on the WebKit thread.
-        mLock.lock();
         mAllowed = nativeGetAllowed(origin);
-        mUpdated = true;
-        mUpdatedCondition.signal();
-        mLock.unlock();
     }
 
     /**
@@ -205,7 +244,6 @@
      */
     public void clear(String origin) {
         // Called on the UI thread.
-        mLock.lock();
         if (mHandler == null) {
             if (mOriginsToClear == null) {
                 mOriginsToClear = new HashSet<String>();
@@ -217,7 +255,6 @@
         } else {
             postMessage(Message.obtain(null, CLEAR, origin));
         }
-        mLock.unlock();
     }
 
     /**
@@ -227,7 +264,6 @@
      */
     public void allow(String origin) {
         // Called on the UI thread.
-        mLock.lock();
         if (mHandler == null) {
             if (mOriginsToAllow == null) {
                 mOriginsToAllow = new HashSet<String>();
@@ -239,7 +275,6 @@
         } else {
             postMessage(Message.obtain(null, ALLOW, origin));
         }
-        mLock.unlock();
     }
 
     /**
diff --git a/core/java/android/webkit/GoogleLocationSettingManager.java b/core/java/android/webkit/GoogleLocationSettingManager.java
index fe7fce6..1b6e77c 100644
--- a/core/java/android/webkit/GoogleLocationSettingManager.java
+++ b/core/java/android/webkit/GoogleLocationSettingManager.java
@@ -35,8 +35,6 @@
  * @hide pending API council review
  */
 class GoogleLocationSettingManager {
-    // The application context.
-    private Context mContext;
     // The observer used to listen to the system setting.
     private GoogleLocationSettingObserver mSettingObserver;
 
@@ -48,6 +46,8 @@
     // by the browser.
     private final static String LAST_READ_USE_LOCATION_FOR_SERVICES =
             "lastReadUseLocationForServices";
+    // The Browser package name.
+    private static final String BROWSER_PACKAGE_NAME = "com.android.browser";
     // The Google origins we consider.
     private static HashSet<String> sGoogleOrigins;
     static {
@@ -57,38 +57,72 @@
         sGoogleOrigins.add("http://www.google.co.uk");
     }
 
-    GoogleLocationSettingManager(Context context) {
-        mContext = context;
+    private static GoogleLocationSettingManager sGoogleLocationSettingManager = null;
+    private static int sRefCount = 0;
+
+    static GoogleLocationSettingManager getInstance() {
+        if (sGoogleLocationSettingManager == null) {
+            sGoogleLocationSettingManager = new GoogleLocationSettingManager();
+        }
+        return sGoogleLocationSettingManager;
     }
 
+    private GoogleLocationSettingManager() {}
+
     /**
      * Starts the manager. Checks whether the setting has changed and
      * installs an observer to listen for future changes.
      */
-    public void start() {
-        maybeApplySetting();
-
+    public void start(Context context) {
+        // Are we running in the browser?
+        if (context == null || !BROWSER_PACKAGE_NAME.equals(context.getPackageName())) {
+            return;
+        }
+        // Increase the refCount
+        sRefCount++;
+        // Are we already registered?
+        if (mSettingObserver != null) {
+            return;
+        }
+        // Read and apply the settings if needed.
+        maybeApplySetting(context);
+        // Register to receive notifications when the system settings change.
         mSettingObserver = new GoogleLocationSettingObserver();
-        mSettingObserver.observe();
+        mSettingObserver.observe(context);
     }
 
     /**
+     * Stops the manager.
+     */
+    public void stop() {
+        // Are we already registered?
+        if (mSettingObserver == null) {
+            return;
+        }
+        if (--sRefCount == 0) {
+            mSettingObserver.doNotObserve();
+            mSettingObserver = null;
+        }
+    }
+    /**
      * Checks to see if the system setting has changed and if so,
      * updates the Geolocation permissions accordingly.
+     * @param the Application context
      */
-    private void maybeApplySetting() {
-        int setting = getSystemSetting();
-        if (settingChanged(setting)) {
+    private void maybeApplySetting(Context context) {
+        int setting = getSystemSetting(context);
+        if (settingChanged(setting, context)) {
             applySetting(setting);
         }
     }
 
     /**
      * Gets the current system setting for 'Use location for Google services'.
+     * @param the Application context
      * @return The system setting.
      */
-    private int getSystemSetting() {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
+    private int getSystemSetting(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(),
                                       Settings.Secure.USE_LOCATION_FOR_SERVICES,
                                       sSystemSettingFalse);
     }
@@ -97,12 +131,13 @@
      * Determines whether the supplied setting has changed from the last
      * value read by the browser.
      * @param setting The setting.
+     * @param the Application context
      * @return Whether the setting has changed from the last value read
      *     by the browser.
      */
-    private boolean settingChanged(int setting) {
+    private boolean settingChanged(int setting, Context context) {
         SharedPreferences preferences =
-                PreferenceManager.getDefaultSharedPreferences(mContext);
+                PreferenceManager.getDefaultSharedPreferences(context);
         // Default to false. If the system setting is false the first time it is ever read by the
         // browser, there's nothing to do.
         int lastReadSetting = sSystemSettingFalse;
@@ -137,20 +172,35 @@
      * This class implements an observer to listen for changes to the
      * system setting.
      */
-    class GoogleLocationSettingObserver extends ContentObserver {
+    private class GoogleLocationSettingObserver extends ContentObserver {
+        private Context mContext;
+
         GoogleLocationSettingObserver() {
             super(new Handler());
         }
 
-        void observe() {
-            ContentResolver resolver = mContext.getContentResolver();
+        void observe(Context context) {
+            if (mContext != null) {
+                return;
+            }
+            ContentResolver resolver = context.getContentResolver();
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                 Settings.Secure.USE_LOCATION_FOR_SERVICES), false, this);
+            mContext = context;
+        }
+
+        void doNotObserve() {
+            if (mContext == null) {
+                return;
+            }
+            ContentResolver resolver = mContext.getContentResolver();
+            resolver.unregisterContentObserver(this);
+            mContext = null;
         }
 
         @Override
         public void onChange(boolean selfChange) {
-            maybeApplySetting();
+            maybeApplySetting(mContext);
         }
     }
 }
diff --git a/core/java/android/webkit/ValueCallback.java b/core/java/android/webkit/ValueCallback.java
new file mode 100644
index 0000000..d8c5cdc
--- /dev/null
+++ b/core/java/android/webkit/ValueCallback.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+/**
+ * A callback interface used to returns values asynchronously
+ *
+ * @hide pending council approval
+ */
+public interface ValueCallback<T>  {
+  /**
+   * Invoked when we have the result
+   */
+  public void onReceiveValue(T value);
+};
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 0e08514..1ae1d85 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -48,9 +48,11 @@
      * Notify the host application of the url for an apple-touch-icon.
      * @param view The WebView that initiated the callback.
      * @param url The icon url.
+     * @param precomposed True if the url is for a precomposed touch icon.
      * @hide pending council approval
      */
-    public void onReceivedTouchIconUrl(WebView view, String url) {}
+    public void onReceivedTouchIconUrl(WebView view, String url,
+            boolean precomposed) {}
 
     /**
      * A callback interface used by the host application to notify
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 3c43fd15..0cfcb95 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -190,12 +190,8 @@
     private boolean         mAllowFileAccess = true;
     private boolean         mLoadWithOverviewMode = false;
 
-    // Manages interaction of the system setting 'Location & security - Share
-    // with Google' and the browser.
-    static GoogleLocationSettingManager sGoogleLocationSettingManager;
-
     // private WebSettings, not accessible by the host activity
-    private int             mDoubleTapToastCount = 3;
+    static private int      mDoubleTapToastCount = 3;
 
     private static final String PREF_FILE = "WebViewSettings";
     private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
@@ -1353,17 +1349,28 @@
         if (DebugFlags.WEB_SETTINGS) {
             junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
         }
-        sGoogleLocationSettingManager = new GoogleLocationSettingManager(mContext);
-        sGoogleLocationSettingManager.start();
+
+        GoogleLocationSettingManager.getInstance().start(mContext);
+
         SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
                 Context.MODE_PRIVATE);
-        mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
-                mDoubleTapToastCount);
+        if (mDoubleTapToastCount > 0) {
+            mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
+                    mDoubleTapToastCount);
+        }
         nativeSync(frame.mNativeFrame);
         mSyncPending = false;
         mEventHandler.createHandler();
     }
 
+    /**
+     * Let the Settings object know that our owner is being destroyed.
+     */
+    /*package*/
+    synchronized void onDestroyed() {
+        GoogleLocationSettingManager.getInstance().stop();
+    }
+
     private int pin(int size) {
         // FIXME: 72 is just an arbitrary max text size value.
         if (size < 1) {
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index ae560fb..0022248 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -20,9 +20,8 @@
 import android.os.Message;
 import android.util.Log;
 
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.Collection;
+import java.util.Map;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -51,28 +50,41 @@
     // Global instance of a WebStorage
     private static WebStorage sWebStorage;
 
-    // We keep the origins, quotas and usages as member values
-    // that we protect via a lock and update in syncValues().
-    // This is needed to transfer this data across threads.
-    private static Lock mLock = new ReentrantLock();
-    private static Condition mUpdateCondition = mLock.newCondition();
-    private static boolean mUpdateAvailable;
-
     // Message ids
     static final int UPDATE = 0;
     static final int SET_QUOTA_ORIGIN = 1;
     static final int DELETE_ORIGIN = 2;
     static final int DELETE_ALL = 3;
+    static final int GET_ORIGINS = 4;
+    static final int GET_USAGE_ORIGIN = 5;
+    static final int GET_QUOTA_ORIGIN = 6;
 
-    private Set <String> mOrigins;
-    private HashMap <String, Long> mQuotas = new HashMap<String, Long>();
-    private HashMap <String, Long> mUsages = new HashMap<String, Long>();
+    // Message ids on the UI thread
+    static final int RETURN_ORIGINS = 0;
+    static final int RETURN_USAGE_ORIGIN = 1;
+    static final int RETURN_QUOTA_ORIGIN = 2;
+
+    private static final String ORIGINS = "origins";
+    private static final String ORIGIN = "origin";
+    private static final String CALLBACK = "callback";
+    private static final String USAGE = "usage";
+    private static final String QUOTA = "quota";
+
+    private Map <String, Origin> mOrigins;
 
     private Handler mHandler = null;
+    private Handler mUIHandler = null;
 
-    private static class Origin {
+    static class Origin {
         String mOrigin = null;
         long mQuota = 0;
+        long mUsage = 0;
+
+        public Origin(String origin, long quota, long usage) {
+            mOrigin = origin;
+            mQuota = quota;
+            mUsage = usage;
+        }
 
         public Origin(String origin, long quota) {
             mOrigin = origin;
@@ -90,11 +102,49 @@
         public long getQuota() {
             return mQuota;
         }
+
+        public long getUsage() {
+            return mUsage;
+        }
     }
 
     /**
      * @hide
-     * Message handler
+     * Message handler, UI side
+     */
+    public void createUIHandler() {
+        if (mUIHandler == null) {
+            mUIHandler = new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case RETURN_ORIGINS: {
+                            Map values = (Map) msg.obj;
+                            Map origins = (Map) values.get(ORIGINS);
+                            ValueCallback<Map> callback = (ValueCallback<Map>) values.get(CALLBACK);
+                            callback.onReceiveValue(origins);
+                            } break;
+
+                        case RETURN_USAGE_ORIGIN: {
+                            Map values = (Map) msg.obj;
+                            ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK);
+                            callback.onReceiveValue((Long)values.get(USAGE));
+                            } break;
+
+                        case RETURN_QUOTA_ORIGIN: {
+                            Map values = (Map) msg.obj;
+                            ValueCallback<Long> callback = (ValueCallback<Long>) values.get(CALLBACK);
+                            callback.onReceiveValue((Long)values.get(QUOTA));
+                            } break;
+                    }
+                }
+            };
+        }
+    }
+
+    /**
+     * @hide
+     * Message handler, webcore side
      */
     public void createHandler() {
         if (mHandler == null) {
@@ -117,6 +167,46 @@
                             nativeDeleteAllData();
                             break;
 
+                        case GET_ORIGINS: {
+                            syncValues();
+                            ValueCallback callback = (ValueCallback) msg.obj;
+                            Map origins = new HashMap(mOrigins);
+                            Map values = new HashMap<String, Object>();
+                            values.put(CALLBACK, callback);
+                            values.put(ORIGINS, origins);
+                            postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
+                            } break;
+
+                        case GET_USAGE_ORIGIN: {
+                            syncValues();
+                            Map values = (Map) msg.obj;
+                            String origin = (String) values.get(ORIGIN);
+                            ValueCallback callback = (ValueCallback) values.get(CALLBACK);
+                            Origin website = mOrigins.get(origin);
+                            Map retValues = new HashMap<String, Object>();
+                            retValues.put(CALLBACK, callback);
+                            if (website != null) {
+                                long usage = website.getUsage();
+                                retValues.put(USAGE, new Long(usage));
+                            }
+                            postUIMessage(Message.obtain(null, RETURN_USAGE_ORIGIN, retValues));
+                            } break;
+
+                        case GET_QUOTA_ORIGIN: {
+                            syncValues();
+                            Map values = (Map) msg.obj;
+                            String origin = (String) values.get(ORIGIN);
+                            ValueCallback callback = (ValueCallback) values.get(CALLBACK);
+                            Origin website = mOrigins.get(origin);
+                            Map retValues = new HashMap<String, Object>();
+                            retValues.put(CALLBACK, callback);
+                            if (website != null) {
+                                long quota = website.getQuota();
+                                retValues.put(QUOTA, new Long(quota));
+                            }
+                            postUIMessage(Message.obtain(null, RETURN_QUOTA_ORIGIN, retValues));
+                            } break;
+
                         case UPDATE:
                             syncValues();
                             break;
@@ -126,82 +216,91 @@
         }
     }
 
+    /*
+     * When calling getOrigins(), getUsageForOrigin() and getQuotaForOrigin(),
+     * we need to get the values from webcore, but we cannot block while doing so
+     * as we used to do, as this could result in a full deadlock (other webcore
+     * messages received while we are still blocked here, see http://b/2127737).
+     *
+     * We have to do everything asynchronously, by providing a callback function.
+     * We post a message on the webcore thread (mHandler) that will get the result
+     * from webcore, and we post it back on the UI thread (using mUIHandler).
+     * We can then use the callback function to return the value.
+     */
+
     /**
      * @hide
      * Returns a list of origins having a database
      */
-    public Set getOrigins() {
-        Set ret = null;
-        mLock.lock();
-        try {
-            mUpdateAvailable = false;
-            update();
-            while (!mUpdateAvailable) {
-                mUpdateCondition.await();
+    public void getOrigins(ValueCallback<Map> callback) {
+        if (callback != null) {
+            if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+                syncValues();
+                callback.onReceiveValue(mOrigins);
+            } else {
+                postMessage(Message.obtain(null, GET_ORIGINS, callback));
             }
-            ret = mOrigins;
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Exception while waiting on the updated origins", e);
-        } finally {
-            mLock.unlock();
         }
-        return ret;
+    }
+
+    /**
+     * Returns a list of origins having a database
+     * should only be called from WebViewCore.
+     */
+    Collection<Origin> getOriginsSync() {
+        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+            update();
+            return mOrigins.values();
+        }
+        return null;
     }
 
     /**
      * @hide
      * Returns the use for a given origin
      */
-    public long getUsageForOrigin(String origin) {
-        long ret = 0;
+    public void getUsageForOrigin(String origin, ValueCallback<Long> callback) {
+        if (callback == null) {
+            return;
+        }
         if (origin == null) {
-          return ret;
+            callback.onReceiveValue(null);
+            return;
         }
-        mLock.lock();
-        try {
-            mUpdateAvailable = false;
-            update();
-            while (!mUpdateAvailable) {
-                mUpdateCondition.await();
-            }
-            Long usage = mUsages.get(origin);
-            if (usage != null) {
-                ret = usage.longValue();
-            }
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Exception while waiting on the updated origins", e);
-        } finally {
-            mLock.unlock();
+        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+            syncValues();
+            Origin website = mOrigins.get(origin);
+            callback.onReceiveValue(new Long(website.getUsage()));
+        } else {
+            HashMap values = new HashMap<String, Object>();
+            values.put(ORIGIN, origin);
+            values.put(CALLBACK, callback);
+            postMessage(Message.obtain(null, GET_USAGE_ORIGIN, values));
         }
-        return ret;
     }
 
     /**
      * @hide
      * Returns the quota for a given origin
      */
-    public long getQuotaForOrigin(String origin) {
-        long ret = 0;
+    public void getQuotaForOrigin(String origin, ValueCallback<Long> callback) {
+        if (callback == null) {
+            return;
+        }
         if (origin == null) {
-          return ret;
+            callback.onReceiveValue(null);
+            return;
         }
-        mLock.lock();
-        try {
-            mUpdateAvailable = false;
-            update();
-            while (!mUpdateAvailable) {
-                mUpdateCondition.await();
-            }
-            Long quota = mQuotas.get(origin);
-            if (quota != null) {
-                ret = quota.longValue();
-            }
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Exception while waiting on the updated origins", e);
-        } finally {
-            mLock.unlock();
+        if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
+            syncValues();
+            Origin website = mOrigins.get(origin);
+            callback.onReceiveValue(new Long(website.getUsage()));
+        } else {
+            HashMap values = new HashMap<String, Object>();
+            values.put(ORIGIN, origin);
+            values.put(CALLBACK, callback);
+            postMessage(Message.obtain(null, GET_QUOTA_ORIGIN, values));
         }
-        return ret;
     }
 
     /**
@@ -256,6 +355,15 @@
     }
 
     /**
+     * Utility function to send a message to the handler on the UI thread
+     */
+    private void postUIMessage(Message msg) {
+        if (mUIHandler != null) {
+            mUIHandler.sendMessage(msg);
+        }
+    }
+
+    /**
      * @hide
      * Get the global instance of WebStorage.
      * @return A single instance of WebStorage.
@@ -284,21 +392,14 @@
      * set the local values with the current ones
      */
     private void syncValues() {
-        mLock.lock();
-        Set tmp = nativeGetOrigins();
-        mOrigins = new HashSet<String>();
-        mQuotas.clear();
-        mUsages.clear();
-        Iterator<String> iter = tmp.iterator();
-        while (iter.hasNext()) {
-            String origin = iter.next();
-            mOrigins.add(origin);
-            mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin)));
-            mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin)));
+        Set<String> tmp = nativeGetOrigins();
+        mOrigins = new HashMap<String, Origin>();
+        for (String origin : tmp) {
+            Origin website = new Origin(origin,
+                                 nativeGetUsageForOrigin(origin),
+                                 nativeGetQuotaForOrigin(origin));
+            mOrigins.put(origin, website);
         }
-        mUpdateAvailable = true;
-        mUpdateCondition.signal();
-        mLock.unlock();
     }
 
     // Native functions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index eaf6c05..51c5e1f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3772,10 +3772,10 @@
                         mZoomButtonsController.setVisible(true);
                         int count = settings.getDoubleTapToastCount();
                         if (mInZoomOverview && count > 0) {
-                            settings.setDoubleTapToastCount(count--);
+                            settings.setDoubleTapToastCount(--count);
                             Toast.makeText(mContext,
                                     com.android.internal.R.string.double_tap_toast,
-                                    Toast.LENGTH_SHORT).show();
+                                    Toast.LENGTH_LONG).show();
                         }
                     }
                 }
@@ -4868,7 +4868,7 @@
                                             / draw.mMinPrefWidth;
                                     mMinZoomScaleFixed = false;
                                 } else {
-                                    mMinZoomScale = mDefaultScale;
+                                    mMinZoomScale = restoreState.mDefaultScale;
                                     mMinZoomScaleFixed = true;
                                 }
                             } else {
@@ -4891,7 +4891,7 @@
                                 && settings.getLoadWithOverviewMode()) {
                             if (restoreState.mViewScale == 0
                                     || (restoreState.mMobileSite
-                                            && mMinZoomScale < mDefaultScale)) {
+                                    && mMinZoomScale < restoreState.mDefaultScale)) {
                                 mInZoomOverview = true;
                             }
                         }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index d4142bb..52bf508 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -37,6 +37,7 @@
 import android.view.View;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 
@@ -100,6 +101,15 @@
 
     private boolean mViewportUserScalable = true;
 
+    /*
+     * range is from 70 to 400.
+     * 0 is a special value means device-dpi. The default scale factor will be
+     * always 100.
+     * -1 means undefined. The default scale factor will be
+     * WebView.DEFAULT_SCALE_PERCENT.
+     */
+    private int mViewportDensityDpi = -1;
+
     private int mRestoredScale = 0;
     private int mRestoredScreenWidthScale = 0;
     private int mRestoredX = 0;
@@ -153,8 +163,10 @@
         // The WebIconDatabase needs to be initialized within the UI thread so
         // just request the instance here.
         WebIconDatabase.getInstance();
-        // Create the WebStorage singleton
-        WebStorage.getInstance();
+        // Create the WebStorage singleton and the UI handler
+        WebStorage.getInstance().createUIHandler();
+        // Create the UI handler for GeolocationPermissions
+        GeolocationPermissions.getInstance().createUIHandler();
         // Send a message to initialize the WebViewCore.
         Message init = sWebCoreHandler.obtainMessage(
                 WebCoreThread.INITIALIZE, this);
@@ -841,6 +853,7 @@
                             synchronized (WebViewCore.this) {
                                 mBrowserFrame.destroy();
                                 mBrowserFrame = null;
+                                mSettings.onDestroyed();
                                 mNativeClass = 0;
                             }
                             break;
@@ -1510,13 +1523,14 @@
     // callbacks. Computes the sum of database quota for all origins.
     private long getUsedQuota() {
         WebStorage webStorage = WebStorage.getInstance();
-        Set<String> origins = webStorage.getOrigins();
+        Collection<WebStorage.Origin> origins = webStorage.getOriginsSync();
+
         if (origins == null) {
             return 0;
         }
         long usedQuota = 0;
-        for (String origin : origins) {
-            usedQuota += webStorage.getQuotaForOrigin(origin);
+        for (WebStorage.Origin website : origins) {
+            usedQuota += website.getQuota();
         }
         return usedQuota;
     }
@@ -1539,6 +1553,7 @@
         float mMaxScale;
         float mViewScale;
         float mTextWrapScale;
+        float mDefaultScale;
         int mScrollX;
         int mScrollY;
         boolean mMobileSite;
@@ -1842,47 +1857,48 @@
         // set the viewport settings from WebKit
         setViewportSettingsFromNative();
 
-        // adjust the default scale to match the density
-        if (WebView.DEFAULT_SCALE_PERCENT != 100) {
-            float adjust = (float) WebView.DEFAULT_SCALE_PERCENT / 100.0f;
-            if (mViewportInitialScale > 0) {
-                mViewportInitialScale *= adjust;
+        // adjust the default scale to match the densityDpi
+        float adjust = 1.0f;
+        if (mViewportDensityDpi == -1) {
+            if (WebView.DEFAULT_SCALE_PERCENT != 100) {
+                adjust = WebView.DEFAULT_SCALE_PERCENT / 100.0f;
             }
-            if (mViewportMinimumScale > 0) {
-                mViewportMinimumScale *= adjust;
-            }
-            if (mViewportMaximumScale > 0) {
-                mViewportMaximumScale *= adjust;
-            }
+        } else if (mViewportDensityDpi > 0) {
+            adjust = (float) mContext.getResources().getDisplayMetrics().densityDpi
+                    / mViewportDensityDpi;
+        }
+        int defaultScale = (int) (adjust * 100);
+
+        if (mViewportInitialScale > 0) {
+            mViewportInitialScale *= adjust;
+        }
+        if (mViewportMinimumScale > 0) {
+            mViewportMinimumScale *= adjust;
+        }
+        if (mViewportMaximumScale > 0) {
+            mViewportMaximumScale *= adjust;
         }
 
         // infer the values if they are not defined.
         if (mViewportWidth == 0) {
             if (mViewportInitialScale == 0) {
-                mViewportInitialScale = WebView.DEFAULT_SCALE_PERCENT;
+                mViewportInitialScale = defaultScale;
             }
         }
         if (mViewportUserScalable == false) {
-            mViewportInitialScale = WebView.DEFAULT_SCALE_PERCENT;
-            mViewportMinimumScale = WebView.DEFAULT_SCALE_PERCENT;
-            mViewportMaximumScale = WebView.DEFAULT_SCALE_PERCENT;
+            mViewportInitialScale = defaultScale;
+            mViewportMinimumScale = defaultScale;
+            mViewportMaximumScale = defaultScale;
         }
-        if (mViewportMinimumScale > mViewportInitialScale) {
-            if (mViewportInitialScale == 0) {
-                mViewportInitialScale = mViewportMinimumScale;
-            } else {
-                mViewportMinimumScale = mViewportInitialScale;
-            }
+        if (mViewportMinimumScale > mViewportInitialScale
+                && mViewportInitialScale != 0) {
+            mViewportMinimumScale = mViewportInitialScale;
         }
-        if (mViewportMaximumScale > 0) {
-            if (mViewportMaximumScale < mViewportInitialScale) {
-                mViewportMaximumScale = mViewportInitialScale;
-            } else if (mViewportInitialScale == 0) {
-                mViewportInitialScale = mViewportMaximumScale;
-            }
+        if (mViewportMaximumScale > 0
+                && mViewportMaximumScale < mViewportInitialScale) {
+            mViewportMaximumScale = mViewportInitialScale;
         }
-        if (mViewportWidth < 0
-                && mViewportInitialScale == WebView.DEFAULT_SCALE_PERCENT) {
+        if (mViewportWidth < 0 && mViewportInitialScale == defaultScale) {
             mViewportWidth = 0;
         }
 
@@ -1899,7 +1915,7 @@
             // we call WebView method from WebCore thread. But not perfect
             // reference is better than no reference.
             webViewWidth = mWebView.getViewWidth();
-            viewportWidth = webViewWidth * 100 / WebView.DEFAULT_SCALE_PERCENT;
+            viewportWidth = (int) (webViewWidth / adjust);
             if (viewportWidth == 0) {
                 Log.w(LOGTAG, "Can't get the viewWidth after the first layout");
             }
@@ -1909,6 +1925,7 @@
         mRestoreState = new RestoreState();
         mRestoreState.mMinScale = mViewportMinimumScale / 100.0f;
         mRestoreState.mMaxScale = mViewportMaximumScale / 100.0f;
+        mRestoreState.mDefaultScale = adjust;
         mRestoreState.mScrollX = mRestoredX;
         mRestoreState.mScrollY = mRestoredY;
         mRestoreState.mMobileSite = (0 == mViewportWidth);
@@ -1930,8 +1947,7 @@
                 mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
                         (float) webViewWidth / mViewportWidth;
             } else {
-                mRestoreState.mTextWrapScale =
-                        WebView.DEFAULT_SCALE_PERCENT / 100.0f;
+                mRestoreState.mTextWrapScale = adjust;
                 // 0 will trigger WebView to turn on zoom overview mode
                 mRestoreState.mViewScale = 0;
             }
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 703cd8e2..31c7814 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -743,7 +743,7 @@
 
         final int maxJump = getMaxScrollAmount();
 
-        if (nextFocused != null && isWithinDeltaOfScreen(nextFocused, maxJump)) {
+        if (nextFocused != null && isWithinDeltaOfScreen(nextFocused, maxJump, getHeight())) {
             nextFocused.getDrawingRect(mTempRect);
             offsetDescendantRectToMyCoords(nextFocused, mTempRect);
             int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
@@ -792,19 +792,19 @@
      *  screen.
      */
     private boolean isOffScreen(View descendant) {
-        return !isWithinDeltaOfScreen(descendant, 0);
+        return !isWithinDeltaOfScreen(descendant, 0, getHeight());
     }
 
     /**
      * @return whether the descendant of this scroll view is within delta
      *  pixels of being on the screen.
      */
-    private boolean isWithinDeltaOfScreen(View descendant, int delta) {
+    private boolean isWithinDeltaOfScreen(View descendant, int delta, int height) {
         descendant.getDrawingRect(mTempRect);
         offsetDescendantRectToMyCoords(descendant, mTempRect);
 
         return (mTempRect.bottom + delta) >= getScrollY()
-                && (mTempRect.top - delta) <= (getScrollY() + getHeight());
+                && (mTempRect.top - delta) <= (getScrollY() + height);
     }
 
     /**
@@ -1124,9 +1124,10 @@
         if (null == currentFocused || this == currentFocused)
             return;
 
-        final int maxJump = mBottom - mTop;
-
-        if (isWithinDeltaOfScreen(currentFocused, maxJump)) {
+        // If the currently-focused view was visible on the screen when the
+        // screen was at the old height, then scroll the screen to make that
+        // view visible with the new screen height.
+        if (isWithinDeltaOfScreen(currentFocused, 0, oldh)) {
             currentFocused.getDrawingRect(mTempRect);
             offsetDescendantRectToMyCoords(currentFocused, mTempRect);
             int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2e3364b..3c61c1c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2874,26 +2874,23 @@
      * @attr ref android.R.styleable#TextView_inputType
      */
     public void setInputType(int type) {
+        final boolean wasPassword = isPasswordInputType(mInputType);
+        final boolean wasVisiblePassword = isVisiblePasswordInputType(mInputType);
         setInputType(type, false);
-        final int variation = type&(EditorInfo.TYPE_MASK_CLASS
-                |EditorInfo.TYPE_MASK_VARIATION);
-        final boolean isPassword = variation
-                == (EditorInfo.TYPE_CLASS_TEXT
-                        |EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
+        final boolean isPassword = isPasswordInputType(type);
+        final boolean isVisiblePassword = isVisiblePasswordInputType(type);
         boolean forceUpdate = false;
         if (isPassword) {
             setTransformationMethod(PasswordTransformationMethod.getInstance());
             setTypefaceByIndex(MONOSPACE, 0);
-        } else if (mTransformation == PasswordTransformationMethod.getInstance()) {
-            // We need to clean up if we were previously in password mode.
-            if (variation != (EditorInfo.TYPE_CLASS_TEXT
-                        |EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)) {
-                setTypefaceByIndex(-1, -1);
-            }
-            forceUpdate = true;
-        } else if (variation == (EditorInfo.TYPE_CLASS_TEXT
-                        |EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)) {
+        } else if (isVisiblePassword) {
             setTypefaceByIndex(MONOSPACE, 0);
+        } else if (wasPassword || wasVisiblePassword) {
+            // not in password mode, clean up typeface and transformation
+            setTypefaceByIndex(-1, -1);
+            if (mTransformation == PasswordTransformationMethod.getInstance()) {
+                forceUpdate = true;
+            }
         }
         
         boolean multiLine = (type&(EditorInfo.TYPE_MASK_CLASS
@@ -2913,6 +2910,22 @@
         if (imm != null) imm.restartInput(this);
     }
 
+    private boolean isPasswordInputType(int inputType) {
+        final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS
+                | EditorInfo.TYPE_MASK_VARIATION);
+        return variation
+                == (EditorInfo.TYPE_CLASS_TEXT
+                        | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
+    }
+
+    private boolean isVisiblePasswordInputType(int inputType) {
+        final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS
+                | EditorInfo.TYPE_MASK_VARIATION);
+        return variation
+                == (EditorInfo.TYPE_CLASS_TEXT
+                        | EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
+    }
+
     /**
      * Directly change the content type integer of the text view, without
      * modifying any other state.
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index 4a9c077..35d637d 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -63,6 +63,7 @@
     private static final String TAG = "ContactHeaderWidget";
 
     private TextView mDisplayNameView;
+    private View mAggregateBadge;
     private TextView mPhoneticNameView;
     private CheckBox mStarredView;
     private FasttrackBadgeWidget mPhotoView;
@@ -159,6 +160,8 @@
 
         mDisplayNameView = (TextView) findViewById(R.id.name);
         mDisplayNameView.setOnLongClickListener(this);
+        mAggregateBadge = findViewById(R.id.aggregate_badge);
+        mAggregateBadge.setVisibility(View.GONE);
 
         mPhoneticNameView = (TextView) findViewById(R.id.phonetic_name);
 
@@ -284,6 +287,13 @@
     }
 
     /**
+     * Turn on/off showing of the aggregate bage element.
+     */
+    public void showAggregateBadge(boolean showBagde) {
+        mAggregateBadge.setVisibility(showBagde ? View.VISIBLE : View.GONE);
+    }
+
+    /**
      * Turn on/off showing of the star element.
      */
     public void showStar(boolean showStar) {
diff --git a/core/res/res/drawable-hdpi/ic_aggregated.png b/core/res/res/drawable-hdpi/ic_aggregated.png
new file mode 100644
index 0000000..7ca15b1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_aggregated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_aggregated.png b/core/res/res/drawable-mdpi/ic_aggregated.png
new file mode 100644
index 0000000..7c2e2b0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_aggregated.png
Binary files differ
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index e800dfa..d19bb04 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -38,8 +38,24 @@
         android:layout_marginTop="5dip"
         android:orientation="vertical">
 
-        <!-- "Name" field is locale-specific. -->
-        <include layout="@layout/contact_header_name"/>
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <ImageView
+                android:id="@+id/aggregate_badge"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingRight="3dip"
+                android:paddingTop="3dip"
+                android:src="@drawable/ic_aggregated"
+            />
+
+            <!-- "Name" field is locale-specific. -->
+            <include layout="@layout/contact_header_name"/>
+
+        </LinearLayout>
 
         <TextView android:id="@+id/status"
             android:layout_width="fill_parent"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e7b379a..c3b7a2c9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3486,13 +3486,29 @@
     <!-- Contacts meta-data attributes -->
     <!-- =============================== -->
 
+    <!-- TODO: remove this deprecated styleable -->
     <declare-styleable name="Icon">
         <attr name="icon" />
         <attr name="mimeType" />
     </declare-styleable>
 
+    <!-- TODO: remove this deprecated styleable -->
     <declare-styleable name="IconDefault">
         <attr name="icon" />
     </declare-styleable>
 
+    <!-- Maps a specific contact data MIME-type to styling information -->
+    <declare-styleable name="ContactsDataKind">
+        <!-- Mime-type handled by this mapping -->
+        <attr name="mimeType" />
+        <!-- Icon used to represent data of this kind -->
+        <attr name="icon" />
+        <!-- Column in data table that summarizes this data -->
+        <attr name="summaryColumn" format="string" />
+        <!-- Column in data table that contains details for this data -->
+        <attr name="detailColumn" format="string" />
+        <!-- Flag indicating that detail should be built from SocialProvider -->
+        <attr name="detailSocialSummary" format="boolean" />
+    </declare-styleable>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 89581e6..b08a58a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1166,6 +1166,9 @@
   <public type="attr" name="accountPreferences" />
   <public type="attr" name="textAppearanceSearchResultSubtitle" />
   <public type="attr" name="textAppearanceSearchResultTitle" />
+  <public type="attr" name="summaryColumn" />
+  <public type="attr" name="detailColumn" />
+  <public type="attr" name="detailSocialSummary" />
 
   <public type="style" name="Theme.Wallpaper" />
   <public type="style" name="Theme.Wallpaper.NoTitleBar" />
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 30c81ab..957f2dd 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -48,50 +48,49 @@
     }
 
     public void data(int[] d) {
-        int size;
-        if(mType != null && mType.mElement != null) {
-            size = mType.mElement.mSize;
-            for(int ct=0; ct < mType.mValues.length; ct++) {
-                if(mType.mValues[ct] != 0) {
-                    size *= mType.mValues[ct];
-                }
-            }
-            if((d.length * 4) < size) {
-                throw new IllegalArgumentException("Array too small for allocation type.");
-            }
-            Log.e("rs", "Alloc data size=" + size);
-            mRS.nAllocationData(mID, d, size);
-            return;
-        }
-        mRS.nAllocationData(mID, d, d.length * 4);
+        subData1D(0, mType.getElementCount(), d);
+    }
+    public void data(short[] d) {
+        subData1D(0, mType.getElementCount(), d);
+    }
+    public void data(byte[] d) {
+        subData1D(0, mType.getElementCount(), d);
+    }
+    public void data(float[] d) {
+        subData1D(0, mType.getElementCount(), d);
     }
 
-    public void data(float[] d) {
-        int size;
-        if(mType != null && mType.mElement != null) {
-            size = mType.mElement.mSize;
-            for(int ct=0; ct < mType.mValues.length; ct++) {
-                if(mType.mValues[ct] != 0) {
-                    size *= mType.mValues[ct];
-                }
-            }
-            if((d.length * 4) < size) {
-                throw new IllegalArgumentException("Array too small for allocation type.");
-            }
-            Log.e("rs", "Alloc data size=" + size);
-            mRS.nAllocationData(mID, d, size);
-            return;
+    private void data1DChecks(int off, int count, int len, int dataSize) {
+        if((off < 0) || (count < 1) || ((off + count) > mType.getElementCount())) {
+            throw new IllegalArgumentException("Offset or Count out of bounds.");
         }
-        mRS.nAllocationData(mID, d, d.length * 4);
+        if((len) < dataSize) {
+            throw new IllegalArgumentException("Array too small for allocation type.");
+        }
     }
 
     public void subData1D(int off, int count, int[] d) {
-        mRS.nAllocationSubData1D(mID, off, count, d, count * 4);
+        int dataSize = mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length * 4, dataSize);
+        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
+    }
+    public void subData1D(int off, int count, short[] d) {
+        int dataSize = mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length * 2, dataSize);
+        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
+    }
+    public void subData1D(int off, int count, byte[] d) {
+        int dataSize = mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length, dataSize);
+        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
+    }
+    public void subData1D(int off, int count, float[] d) {
+        int dataSize = mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length * 4, dataSize);
+        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
     }
 
-    public void subData1D(int off, int count, float[] d) {
-        mRS.nAllocationSubData1D(mID, off, count, d, d.length * 4);
-    }
+
 
     public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
         mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4);
@@ -213,11 +212,15 @@
     static public Allocation createSized(RenderScript rs, Element e, int count)
         throws IllegalArgumentException {
 
-        int id = rs.nAllocationCreateSized(e.mID, count);
+        Type.Builder b = new Type.Builder(rs, e);
+        b.add(Dimension.X, count);
+        Type t = b.create();
+
+        int id = rs.nAllocationCreateTyped(t.mID);
         if(id == 0) {
             throw new IllegalStateException("Bad element.");
         }
-        return new Allocation(id, rs, null);
+        return new Allocation(id, rs, t);
     }
 
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 04c36fd..0a586c4 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -26,18 +26,40 @@
     int mSize;
     Entry[] mEntries;
 
+    int getSizeBytes() {
+        return mSize;
+    }
+    int getComponentCount() {
+        return mEntries.length;
+    }
+    Element.DataType getComponentDataType(int num) {
+        return mEntries[num].mType;
+    }
+    Element.DataKind getComponentDataKind(int num) {
+        return mEntries[num].mKind;
+    }
+    boolean getComponentIsNormalized(int num) {
+        return mEntries[num].mIsNormalized;
+    }
+    int getComponentBits(int num) {
+        return mEntries[num].mBits;
+    }
+    String getComponentName(int num) {
+        return mEntries[num].mName;
+    }
+
     static class Entry {
-        Element mElement;
+        //Element mElement;
         Element.DataType mType;
         Element.DataKind mKind;
         boolean mIsNormalized;
         int mBits;
         String mName;
 
-        Entry(Element e, int bits) {
-            mElement = e;
-            int mBits = bits;
-        }
+        //Entry(Element e, int bits) {
+            //mElement = e;
+            //int mBits = bits;
+        //}
 
         Entry(DataType dt, DataKind dk, boolean isNorm, int bits, String name) {
             mType = dt;
@@ -266,14 +288,11 @@
         int bits = 0;
         for (int ct=0; ct < e.mEntries.length; ct++) {
             Entry en = e.mEntries[ct];
-            if(en.mElement !=  null) {
+            //if(en.mElement !=  null) {
                 //rs.nElementAdd(en.mElement.mID);
-            } else {
-                int norm = 0;
-                if (en.mIsNormalized) {
-                    norm = 1;
-                }
-                rs.nElementAdd(en.mKind.mID, en.mType.mID, norm, en.mBits, en.mName);
+            //} else
+            {
+                rs.nElementAdd(en.mKind.mID, en.mType.mID, en.mIsNormalized, en.mBits, en.mName);
                 bits += en.mBits;
             }
         }
@@ -308,11 +327,11 @@
             mEntryCount++;
         }
 
-        public Builder add(Element e) throws IllegalArgumentException {
-            Entry en = new Entry(e, e.mSize * 8);
-            addEntry(en);
-            return this;
-        }
+        //public Builder add(Element e) throws IllegalArgumentException {
+            //Entry en = new Entry(e, e.mSize * 8);
+            //addEntry(en);
+            //return this;
+        //}
 
         public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits, String name) {
             Entry en = new Entry(dt, dk, isNormalized, bits, name);
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index d35c5e3..5831d13 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -80,7 +80,7 @@
     native int  nFileOpen(byte[] name);
 
     native void nElementBegin();
-    native void nElementAdd(int kind, int type, int norm, int bits, String s);
+    native void nElementAdd(int kind, int type, boolean norm, int bits, String s);
     native int  nElementCreate();
 
     native void nTypeBegin(int elementID);
@@ -90,17 +90,19 @@
     native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs);
 
     native int  nAllocationCreateTyped(int type);
-    native int  nAllocationCreateSized(int elem, int count);
+    //native int  nAllocationCreateSized(int elem, int count);
     native int  nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp);
     native int  nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp);
     native int  nAllocationCreateFromAssetStream(int dstFmt, boolean genMips, int assetStream);
 
     native void nAllocationUploadToTexture(int alloc, int baseMioLevel);
     native void nAllocationUploadToBufferObject(int alloc);
-    native void nAllocationData(int id, int[] d, int sizeBytes);
-    native void nAllocationData(int id, float[] d, int sizeBytes);
+
     native void nAllocationSubData1D(int id, int off, int count, int[] d, int sizeBytes);
+    native void nAllocationSubData1D(int id, int off, int count, short[] d, int sizeBytes);
+    native void nAllocationSubData1D(int id, int off, int count, byte[] d, int sizeBytes);
     native void nAllocationSubData1D(int id, int off, int count, float[] d, int sizeBytes);
+
     native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, int[] d, int sizeBytes);
     native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d, int sizeBytes);
     native void nAllocationRead(int id, int[] d);
diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java
index 5d87654..dc74c61 100644
--- a/graphics/java/android/renderscript/SimpleMesh.java
+++ b/graphics/java/android/renderscript/SimpleMesh.java
@@ -162,7 +162,6 @@
         }
 
         public SimpleMesh create() {
-            Log.e("rs", "SimpleMesh create");
             SimpleMesh sm = internalCreate(mRS, this);
             sm.mVertexTypes = new Type[mVertexTypeCount];
             for(int ct=0; ct < mVertexTypeCount; ct++) {
@@ -177,7 +176,7 @@
     public static class TriangleMeshBuilder {
         float mVtxData[];
         int mVtxCount;
-        int mIndexData[];
+        short mIndexData[];
         int mIndexCount;
         RenderScript mRS;
         Element mElement;
@@ -191,7 +190,7 @@
             mVtxCount = 0;
             mIndexCount = 0;
             mVtxData = new float[128];
-            mIndexData = new int[128];
+            mIndexData = new short[128];
             mVtxSize = vtxSize;
             mNorm = norm;
             mTex = tex;
@@ -268,13 +267,13 @@
 
         public void addTriangle(int idx1, int idx2, int idx3) {
             if((mIndexCount + 3) >= mIndexData.length) {
-                int t[] = new int[mIndexData.length * 2];
+                short t[] = new short[mIndexData.length * 2];
                 System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
                 mIndexData = t;
             }
-            mIndexData[mIndexCount++] = idx1;
-            mIndexData[mIndexCount++] = idx2;
-            mIndexData[mIndexCount++] = idx3;
+            mIndexData[mIndexCount++] = (short)idx1;
+            mIndexData[mIndexCount++] = (short)idx2;
+            mIndexData[mIndexCount++] = (short)idx3;
         }
 
         public SimpleMesh create() {
@@ -309,10 +308,6 @@
             vertexAlloc.data(mVtxData);
             vertexAlloc.uploadToBufferObject();
 
-            // This is safe because length is a pow2
-            for(int ct=0; ct < (mIndexCount+1); ct += 2) {
-                mIndexData[ct >> 1] = mIndexData[ct] | (mIndexData[ct+1] << 16);
-            }
             indexAlloc.data(mIndexData);
             indexAlloc.uploadToBufferObject();
 
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index b6b7adf..df60990 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -23,13 +23,74 @@
  *
  **/
 public class Type extends BaseObj {
-    Dimension[] mDimensions;
-    int[] mValues;
+    int mDimX;
+    int mDimY;
+    int mDimZ;
+    boolean mDimLOD;
+    boolean mDimFaces;
+    int mElementCount;
     Element mElement;
+
     private int mNativeCache;
     Class mJavaClass;
 
 
+    public int getX() {
+        return mDimX;
+    }
+    public int getY() {
+        return mDimY;
+    }
+    public int getZ() {
+        return mDimZ;
+    }
+    public boolean getLOD() {
+        return mDimLOD;
+    }
+    public boolean getFaces() {
+        return mDimFaces;
+    }
+    public int getElementCount() {
+        return mElementCount;
+    }
+
+    void calcElementCount() {
+        boolean hasLod = getLOD();
+        int x = getX();
+        int y = getY();
+        int z = getZ();
+        int faces = 1;
+        if(getFaces()) {
+            faces = 6;
+        }
+        if(x == 0) {
+            x = 1;
+        }
+        if(y == 0) {
+            y = 1;
+        }
+        if(z == 0) {
+            z = 1;
+        }
+
+        int count = x * y * z * faces;
+        if(hasLod && (x > 1) && (y > 1) && (z > 1)) {
+            if(x > 1) {
+                x >>= 1;
+            }
+            if(y > 1) {
+                y >>= 1;
+            }
+            if(z > 1) {
+                z >>= 1;
+            }
+
+            count += x * y * z * faces;
+        }
+        mElementCount = count;
+    }
+
+
     Type(int id, RenderScript rs) {
         super(rs);
         mID = id;
@@ -131,12 +192,25 @@
         public Type create() {
             Type t = internalCreate(mRS, this);
             t.mElement = mElement;
-            t.mDimensions = new Dimension[mEntryCount];
-            t.mValues = new int[mEntryCount];
+
             for(int ct=0; ct < mEntryCount; ct++) {
-                t.mDimensions[ct] = mEntries[ct].mDim;
-                t.mValues[ct] = mEntries[ct].mValue;
+                if(mEntries[ct].mDim == Dimension.X) {
+                    t.mDimX = mEntries[ct].mValue;
+                }
+                if(mEntries[ct].mDim == Dimension.Y) {
+                    t.mDimY = mEntries[ct].mValue;
+                }
+                if(mEntries[ct].mDim == Dimension.Z) {
+                    t.mDimZ = mEntries[ct].mValue;
+                }
+                if(mEntries[ct].mDim == Dimension.LOD) {
+                    t.mDimLOD = mEntries[ct].mValue != 0;
+                }
+                if(mEntries[ct].mDim == Dimension.FACE) {
+                    t.mDimFaces = mEntries[ct].mValue != 0;
+                }
             }
+            t.calcElementCount();
             return t;
         }
     }
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index c7b5448..56a4223 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -181,7 +181,7 @@
 
 
 static void
-nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jint norm, jint bits, jstring name)
+nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jboolean norm, jint bits, jstring name)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
     const char* n = NULL;
@@ -359,14 +359,6 @@
     return (jint) rsAllocationCreateTyped(con, (RsElement)e);
 }
 
-static jint
-nAllocationCreateSized(JNIEnv *_env, jobject _this, jint e, jint count)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nAllocationCreateSized, con(%p), e(%p), count(%i)", con, (RsElement)e, count);
-    return (jint) rsAllocationCreateSized(con, (RsElement)e, count);
-}
-
 static void
 nAllocationUploadToTexture(JNIEnv *_env, jobject _this, jint a, jint mip)
 {
@@ -476,44 +468,44 @@
 
 
 static void
-nAllocationData_i(JNIEnv *_env, jobject _this, jint alloc, jintArray data, int sizeBytes)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationData_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocationData(con, (RsAllocation)alloc, ptr, sizeBytes);
-    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
-nAllocationData_f(JNIEnv *_env, jobject _this, jint alloc, jfloatArray data, int sizeBytes)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationData_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocationData(con, (RsAllocation)alloc, ptr, sizeBytes);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
-}
-
-static void
 nAllocationSubData1D_i(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jintArray data, int sizeBytes)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAllocation)alloc, offset, count, len);
+    LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
     jint *ptr = _env->GetIntArrayElements(data, NULL);
     rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
     _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
+nAllocationSubData1D_s(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jshortArray data, int sizeBytes)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation1DSubData_s, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
+    jshort *ptr = _env->GetShortArrayElements(data, NULL);
+    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
+    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationSubData1D_b(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jbyteArray data, int sizeBytes)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation1DSubData_b, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
 nAllocationSubData1D_f(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jfloatArray data, int sizeBytes)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAllocation)alloc, offset, count, len);
+    LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
     jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
     rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
     _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
@@ -1323,7 +1315,7 @@
 {"nFileOpen",                      "([B)I",                                (void*)nFileOpen },
 
 {"nElementBegin",                  "()V",                                  (void*)nElementBegin },
-{"nElementAdd",                    "(IIIILjava/lang/String;)V",            (void*)nElementAdd },
+{"nElementAdd",                    "(IIZILjava/lang/String;)V",            (void*)nElementAdd },
 {"nElementCreate",                 "()I",                                  (void*)nElementCreate },
 
 {"nTypeBegin",                     "(I)V",                                 (void*)nTypeBegin },
@@ -1333,15 +1325,14 @@
 {"nTypeSetupFields",               "(Landroid/renderscript/Type;[I[I[Ljava/lang/reflect/Field;)V", (void*)nTypeSetupFields },
 
 {"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
-{"nAllocationCreateSized",         "(II)I",                                (void*)nAllocationCreateSized },
 {"nAllocationCreateFromBitmap",    "(IZLandroid/graphics/Bitmap;)I",       (void*)nAllocationCreateFromBitmap },
 {"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I",      (void*)nAllocationCreateFromBitmapBoxed },
 {"nAllocationCreateFromAssetStream","(IZI)I",                              (void*)nAllocationCreateFromAssetStream },
 {"nAllocationUploadToTexture",     "(II)V",                                (void*)nAllocationUploadToTexture },
 {"nAllocationUploadToBufferObject","(I)V",                                 (void*)nAllocationUploadToBufferObject },
-{"nAllocationData",                "(I[II)V",                              (void*)nAllocationData_i },
-{"nAllocationData",                "(I[FI)V",                              (void*)nAllocationData_f },
 {"nAllocationSubData1D",           "(III[II)V",                            (void*)nAllocationSubData1D_i },
+{"nAllocationSubData1D",           "(III[SI)V",                            (void*)nAllocationSubData1D_s },
+{"nAllocationSubData1D",           "(III[BI)V",                            (void*)nAllocationSubData1D_b },
 {"nAllocationSubData1D",           "(III[FI)V",                            (void*)nAllocationSubData1D_f },
 {"nAllocationSubData2D",           "(IIIII[II)V",                          (void*)nAllocationSubData2D_i },
 {"nAllocationSubData2D",           "(IIIII[FI)V",                          (void*)nAllocationSubData2D_f },
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index e534447..6500791 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1227,44 +1227,46 @@
             enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
        }
 
-
-        // output audio to hardware
-        if (mSuspended) {
-            usleep(kMaxBufferRecoveryInUsecs);
+        if (LIKELY(enabledTracks)) {
+            // mix buffers...
+            mAudioMixer->process(curBuf);
+            sleepTime = 0;
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
         } else {
-            if (LIKELY(enabledTracks)) {
-                // mix buffers...
-                mAudioMixer->process(curBuf);
+            sleepTime += kBufferRecoveryInUsecs;
+            if (sleepTime > kMaxBufferRecoveryInUsecs) {
+                sleepTime = kMaxBufferRecoveryInUsecs;
+            }
+            // There was nothing to mix this round, which means all
+            // active tracks were late. Sleep a little bit to give
+            // them another chance. If we're too late, write 0s to audio
+            // hardware to avoid underrun.
+            if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) {
+                memset (curBuf, 0, mixBufferSize);
                 sleepTime = 0;
-                standbyTime = systemTime() + kStandbyTimeInNsecs;
-            } else {
-                sleepTime += kBufferRecoveryInUsecs;
-                // There was nothing to mix this round, which means all
-                // active tracks were late. Sleep a little bit to give
-                // them another chance. If we're too late, write 0s to audio
-                // hardware to avoid underrun.
-                if (mBytesWritten == 0 || sleepTime < kMaxBufferRecoveryInUsecs) {
-                    usleep(kBufferRecoveryInUsecs);
-                } else {
-                    memset (curBuf, 0, mixBufferSize);
-                    sleepTime = 0;
-                }
             }
-            // sleepTime == 0 means PCM data were written to mMixBuffer[]
-            if (sleepTime == 0) {
-                mLastWriteTime = systemTime();
-                mInWrite = true;
-                int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
-                if (bytesWritten > 0) mBytesWritten += bytesWritten;
-                mNumWrites++;
-                mInWrite = false;
-                mStandby = false;
-                nsecs_t delta = systemTime() - mLastWriteTime;
-                if (delta > maxPeriod) {
-                    LOGW("write blocked for %llu msecs", ns2ms(delta));
-                    mNumDelayedWrites++;
-                }
+        }
+
+        if (mSuspended) {
+            sleepTime = kMaxBufferRecoveryInUsecs;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            LOGV("mOutput->write() thread %p frames %d", this, mFrameCount);
+            int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
+            if (bytesWritten > 0) mBytesWritten += bytesWritten;
+            mNumWrites++;
+            mInWrite = false;
+            mStandby = false;
+            nsecs_t delta = systemTime() - mLastWriteTime;
+            if (delta > maxPeriod) {
+                LOGW("write blocked for %llu msecs, thread %p", ns2ms(delta), this);
+                mNumDelayedWrites++;
             }
+        } else {
+            usleep(sleepTime);
         }
 
         // finally let go of all our tracks, without the lock held
@@ -1718,50 +1720,55 @@
             }
        }
 
-        // output audio to hardware
-        if (mSuspended) {
-            usleep(kMaxBufferRecoveryInUsecs);
+        if (activeTrack != 0) {
+            AudioBufferProvider::Buffer buffer;
+            size_t frameCount = mFrameCount;
+            curBuf = (int8_t *)mMixBuffer;
+            // output audio to hardware
+            while(frameCount) {
+                buffer.frameCount = frameCount;
+                activeTrack->getNextBuffer(&buffer);
+                if (UNLIKELY(buffer.raw == 0)) {
+                    memset(curBuf, 0, frameCount * mFrameSize);
+                    break;
+                }
+                memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+                frameCount -= buffer.frameCount;
+                curBuf += buffer.frameCount * mFrameSize;
+                activeTrack->releaseBuffer(&buffer);
+            }
+            sleepTime = 0;
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
         } else {
-            if (activeTrack != 0) {
-                AudioBufferProvider::Buffer buffer;
-                size_t frameCount = mFrameCount;
-                curBuf = (int8_t *)mMixBuffer;
-                // output audio to hardware
-                while(frameCount) {
-                    buffer.frameCount = frameCount;
-                    activeTrack->getNextBuffer(&buffer);
-                    if (UNLIKELY(buffer.raw == 0)) {
-                        memset(curBuf, 0, frameCount * mFrameSize);
-                        break;
-                    }
-                    memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
-                    frameCount -= buffer.frameCount;
-                    curBuf += buffer.frameCount * mFrameSize;
-                    activeTrack->releaseBuffer(&buffer);
-                }
+            sleepTime += kBufferRecoveryInUsecs;
+            if (sleepTime > kMaxBufferRecoveryInUsecs) {
+                sleepTime = kMaxBufferRecoveryInUsecs;
+            }
+            // There was nothing to mix this round, which means all
+            // active tracks were late. Sleep a little bit to give
+            // them another chance. If we're too late, write 0s to audio
+            // hardware to avoid underrun.
+            if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs &&
+                AudioSystem::isLinearPCM(mFormat)) {
+                memset (mMixBuffer, 0, mFrameCount * mFrameSize);
                 sleepTime = 0;
-                standbyTime = systemTime() + kStandbyTimeInNsecs;
-            } else {
-                sleepTime += kBufferRecoveryInUsecs;
-                if (mBytesWritten == 0 || !AudioSystem::isLinearPCM(mFormat) ||
-                    sleepTime < kMaxBufferRecoveryInUsecs) {
-                    usleep(kBufferRecoveryInUsecs);
-                } else {
-                    memset (mMixBuffer, 0, mFrameCount * mFrameSize);
-                    sleepTime = 0;
-                }
             }
+        }
 
-            // sleepTime == 0 means PCM data were written to mMixBuffer[]
-            if (sleepTime == 0) {
-                mLastWriteTime = systemTime();
-                mInWrite = true;
-                int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
-                if (bytesWritten) mBytesWritten += bytesWritten;
-                mNumWrites++;
-                mInWrite = false;
-                mStandby = false;
-            }
+        if (mSuspended) {
+            sleepTime = kMaxBufferRecoveryInUsecs;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+            if (bytesWritten) mBytesWritten += bytesWritten;
+            mNumWrites++;
+            mInWrite = false;
+            mStandby = false;
+        } else {
+            usleep(sleepTime);
         }
 
         // finally let go of removed track, without the lock held
@@ -1913,38 +1920,40 @@
             }
 
             enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
-       }
+        }
 
-        bool mustSleep = true;
         if (LIKELY(enabledTracks)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
-            if (!mSuspended) {
-                for (size_t i = 0; i < outputTracks.size(); i++) {
-                    outputTracks[i]->write(curBuf, mFrameCount);
-                    mustSleep = false;
-                }
-                mStandby = false;
-                mBytesWritten += mixBufferSize;
-            }
+            sleepTime = 0;
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
         } else {
-            // flush remaining overflow buffers in output tracks
-            for (size_t i = 0; i < outputTracks.size(); i++) {
-                if (outputTracks[i]->isActive()) {
-                    outputTracks[i]->write(curBuf, 0);
-                    standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    mustSleep = false;
-                }
+            sleepTime += kBufferRecoveryInUsecs;
+            if (sleepTime > kMaxBufferRecoveryInUsecs) {
+                sleepTime = kMaxBufferRecoveryInUsecs;
+            }
+            // There was nothing to mix this round, which means all
+            // active tracks were late. Sleep a little bit to give
+            // them another chance. If we're too late, write 0s to audio
+            // hardware to avoid underrun.
+            if (mBytesWritten != 0 && sleepTime >= kMaxBufferRecoveryInUsecs) {
+                memset (curBuf, 0, mixBufferSize);
+                sleepTime = 0;
             }
         }
-        if (mustSleep) {
-//            LOGV("threadLoop() sleeping %d", sleepTime);
-            usleep(sleepTime);
-            if (sleepTime < kMaxBufferRecoveryInUsecs) {
-                sleepTime += kBufferRecoveryInUsecs;
+
+        if (mSuspended) {
+            sleepTime = kMaxBufferRecoveryInUsecs;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            for (size_t i = 0; i < outputTracks.size(); i++) {
+                outputTracks[i]->write(curBuf, mFrameCount);
             }
+            mStandby = false;
+            mBytesWritten += mixBufferSize;
         } else {
-            sleepTime = kBufferRecoveryInUsecs;
+            usleep(sleepTime);
         }
 
         // finally let go of all our tracks, without the lock held
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 04f6e07..3e4c9af 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -112,8 +112,8 @@
 #endif
     rsAssert(mRootScript->mEnviroment.mIsRoot);
 
-    //glColor4f(1,1,1,1);
-    //glEnable(GL_LIGHT0);
+    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
+    eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
     glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     glEnable(GL_POINT_SMOOTH);
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 37a3bd5..3ac5df5 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -736,6 +736,28 @@
                     if (time != -1) {
                         values.put(Images.Media.DATE_TAKEN, time);
                     }
+
+                    int orientation = exif.getAttributeInt(
+                        ExifInterface.TAG_ORIENTATION, -1);
+                    if (orientation != -1) {
+                        // We only recognize a subset of orientation tag values.
+                        int degree;
+                        switch(orientation) {
+                            case ExifInterface.ORIENTATION_ROTATE_90:
+                                degree = 90;
+                                break;
+                            case ExifInterface.ORIENTATION_ROTATE_180:
+                                degree = 180;
+                                break;
+                            case ExifInterface.ORIENTATION_ROTATE_270:
+                                degree = 270;
+                                break;
+                            default:
+                                degree = 0;
+                                break;
+                        }
+                        values.put(Images.Media.ORIENTATION, degree);
+                    }
                 }
             }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
index 0401390..53afb1d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -32,6 +32,29 @@
         return s;
     }
 
+    public static boolean getWMAEnable() {
+        // push all the property into one big table
+        int wmaEnable = 1;
+        wmaEnable = SystemProperties.getInt("ro.media.dec.aud.wma.enabled",
+                wmaEnable);
+        if (wmaEnable == 1) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static boolean getWMVEnable(){
+        int wmvEnable = 1;
+        wmvEnable = SystemProperties.getInt("ro.media.dec.vid.wmv.enabled",
+                wmvEnable);
+        if (wmvEnable == 1) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     public static void createVideoProfileTable() {
         // push all the property into one big table
         String encoderType = getVideoCodecProperty();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
index 30e2d6c..392d1d5 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
@@ -18,6 +18,7 @@
 
 import com.android.mediaframeworktest.MediaFrameworkTest;
 import com.android.mediaframeworktest.MediaNames;
+import com.android.mediaframeworktest.MediaProfileReader;
 
 import android.content.Context;
 import android.test.ActivityInstrumentationTestCase;
@@ -35,11 +36,15 @@
 public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {    
    private boolean duratoinWithinTolerence = false;
    private String TAG = "MediaPlayerApiTest";
+   private boolean isWMAEnable = false;
+   private boolean isWMVEnable = false;
    
    Context mContext;
   
    public MediaPlayerApiTest() {
      super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+     isWMAEnable = MediaProfileReader.getWMAEnable();
+     isWMVEnable = MediaProfileReader.getWMVEnable();
    }
 
     protected void setUp() throws Exception {
@@ -82,9 +87,11 @@
     
     @MediumTest
     public void testWMA9GetDuration() throws Exception {
-      int duration = CodecTest.getDuration(MediaNames.WMA9); 
-      duratoinWithinTolerence = verifyDuration(duration, MediaNames.WMA9_LENGTH);
-      assertTrue("WMA9 getDuration", duratoinWithinTolerence);  
+      if (isWMAEnable) {
+            int duration = CodecTest.getDuration(MediaNames.WMA9);
+            duratoinWithinTolerence = verifyDuration(duration, MediaNames.WMA9_LENGTH);
+            assertTrue("WMA9 getDuration", duratoinWithinTolerence);
+        }
     }
 
     @MediumTest
@@ -123,8 +130,10 @@
     
     @LargeTest
     public void testWMA9GetCurrentPosition() throws Exception {
-      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.WMA9);  
-      assertTrue("WMA9 GetCurrentPosition", currentPosition);  
+        if (isWMAEnable) {
+            boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.WMA9);
+            assertTrue("WMA9 GetCurrentPosition", currentPosition);
+        }
     }
     
     @LargeTest
@@ -160,8 +169,10 @@
    
     @LargeTest
     public void testWMA9Pause() throws Exception {
-      boolean isPaused = CodecTest.pause(MediaNames.WMA9);  
-      assertTrue("WMA9 Pause", isPaused);  
+        if (isWMAEnable) {
+            boolean isPaused = CodecTest.pause(MediaNames.WMA9);
+            assertTrue("WMA9 Pause", isPaused);
+        }
     }
   
     @LargeTest
@@ -269,8 +280,10 @@
     
     @LargeTest
     public void testWMA9SeekTo() throws Exception {
-      boolean isLoop = CodecTest.seekTo(MediaNames.WMA9);  
-      assertTrue("WMA9 seekTo", isLoop);  
+        if (isWMAEnable) {
+            boolean isLoop = CodecTest.seekTo(MediaNames.WMA9);
+            assertTrue("WMA9 seekTo", isLoop);
+        }
     }
     
     @LargeTest
@@ -309,8 +322,10 @@
     @Suppress
     @LargeTest
     public void testWMA9SeekToEnd() throws Exception {
-      boolean isEnd = CodecTest.seekToEnd(MediaNames.WMA9);  
-      assertTrue("WMA9 seekToEnd", isEnd);  
+        if (isWMAEnable) {
+            boolean isEnd = CodecTest.seekToEnd(MediaNames.WMA9);
+            assertTrue("WMA9 seekToEnd", isEnd);
+        }
     }
     
     @LargeTest
@@ -327,8 +342,10 @@
     
     @LargeTest
     public void testWAVSeekToEnd() throws Exception {
-      boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);  
-      assertTrue("WAV seekToEnd", isEnd);  
+        if (isWMVEnable) {
+            boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);
+            assertTrue("WAV seekToEnd", isEnd);
+        }
     }  
     
     @MediumTest
@@ -385,8 +402,12 @@
    
     @LargeTest
     public void testVideoWMVSeekTo() throws Exception {
-      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WMV);
-      assertTrue("WMV SeekTo", isSeek);         
+        Log.v(TAG, "wmv not enable");
+        if (isWMVEnable) {
+            Log.v(TAG, "wmv enable");
+            boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WMV);
+            assertTrue("WMV SeekTo", isSeek);
+        }
     }
     
     @LargeTest
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index b4d265d..690eff6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -239,7 +239,7 @@
             validVideo = true;
         }
         Log.v(TAG, "width = " + mOutputVideoWidth + " height = " + mOutputVideoHeight + " Duration = " + mOutputDuration);
-        removeFile(filePath);
+        //removeFile(filePath);
         return validVideo;
     }
     
@@ -428,8 +428,9 @@
     }
 
     @LargeTest
-    //est cases for the new codec
+    //test cases for the new codec
     public void testDeviceSpecificCodec() throws Exception {
+        int noOfFailure = 0;
         boolean recordSuccess = false;
         String deviceType = MediaProfileReader.getDeviceType();
         Log.v(TAG, "deviceType = " + deviceType);
@@ -450,10 +451,18 @@
                         } else {
                             recordSuccess = recordVideoWithPara(encoder[i], audio[j], "low");
                         }
-                        assertTrue((encoder[i] + audio[j]), recordSuccess);
+                        if (!recordSuccess){
+                            Log.v(TAG, "testDeviceSpecificCodec failed");
+                            Log.v(TAG, "Encoder = " + encoder[i] + "Audio Encoder = " + audio[j]);
+                            noOfFailure++;
+                        }
+                       //assertTrue((encoder[i] + audio[j]), recordSuccess);
                     }
                 }
             }
         }
+        if (noOfFailure != 0){
+            assertTrue("testDeviceSpecificCodec", false);
+        }
     }
 }
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
index 13b4952..9909905 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
@@ -17,7 +17,7 @@
 package com.android.server.vpn;
 
 import android.net.vpn.L2tpIpsecProfile;
-import android.security.CertTool;
+import android.security.Credentials;
 
 import java.io.IOException;
 
@@ -30,16 +30,18 @@
     @Override
     protected void connect(String serverIp, String username, String password)
             throws IOException {
+        L2tpIpsecProfile p = getProfile();
         // IPSEC
         DaemonProxy ipsec = startDaemon(IPSEC);
         ipsec.sendCommand(serverIp, L2tpService.L2TP_PORT,
-                getUserkeyPath(), getUserCertPath(), getCaCertPath());
+                Credentials.USER_PRIVATE_KEY + p.getUserCertificate(),
+                Credentials.USER_CERTIFICATE + p.getUserCertificate(),
+                Credentials.CA_CERTIFICATE + p.getCaCertificate());
         ipsec.closeControlSocket();
 
         sleep(2000); // 2 seconds
 
         // L2TP
-        L2tpIpsecProfile p = getProfile();
         MtpdHelper.sendCommand(this, L2tpService.L2TP_DAEMON, serverIp,
                 L2tpService.L2TP_PORT,
                 (p.isSecretEnabled() ? p.getSecretString() : null),
@@ -51,19 +53,4 @@
         stopDaemon(IPSEC);
         stopDaemon(MtpdHelper.MTPD);
     }
-
-    private String getCaCertPath() {
-        return CertTool.getInstance().getCaCertificate(
-                getProfile().getCaCertificate());
-    }
-
-    private String getUserCertPath() {
-        return CertTool.getInstance().getUserCertificate(
-                getProfile().getUserCertificate());
-    }
-
-    private String getUserkeyPath() {
-        return CertTool.getInstance().getUserPrivateKey(
-                getProfile().getUserCertificate());
-    }
 }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 9d2fc27..b2e3a8c 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2131,7 +2131,9 @@
         long milliseconds = event.timestamp / 1000000;
         synchronized (mLocks) {
             float distance = event.values[0];
-            if (distance >= 0.0 && distance < PROXIMITY_THRESHOLD) {
+            // compare against getMaximumRange to support sensors that only return 0 or 1
+            if (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
+                    distance < mProximitySensor.getMaximumRange()) {
                 if (mSpew) {
                     Log.d(TAG, "onSensorChanged: proximity active, distance: " + distance);
                 }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 954930e..01bc919 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -71,7 +71,7 @@
     /** {@hide} */
     public EnterpriseField phase2 = new EnterpriseField("phase2");
     /** {@hide} */
-    public EnterpriseField identity = new EnterpriseField("anonymous_identity");
+    public EnterpriseField identity = new EnterpriseField("identity");
     /** {@hide} */
     public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
     /** {@hide} */
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index e3d8bf4..5638480 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -907,6 +907,7 @@
                             }
                         }
                     } else if (newState == SupplicantState.DISCONNECTED) {
+                        mHaveIpAddress = false;
                         if (isDriverStopped() || mDisconnectExpected) {
                             handleDisconnectedState(DetailedState.DISCONNECTED);
                         } else {
@@ -1007,20 +1008,17 @@
                     setNotificationVisible(false, 0, false, 0);
                     boolean wasDisconnectPending = mDisconnectPending;
                     cancelDisconnect();
-                    if (!TextUtils.equals(mWifiInfo.getSSID(), mLastSsid)) {
-                        /*
-                         * The connection is fully configured as far as link-level
-                         * connectivity is concerned, but we may still need to obtain
-                         * an IP address. But do this only if we are connecting to
-                         * a different network than we were connected to previously.
-                         */
-                        if (wasDisconnectPending) {
-                            DetailedState saveState = getNetworkInfo().getDetailedState();
-                            handleDisconnectedState(DetailedState.DISCONNECTED);
-                            setDetailedStateInternal(saveState);
-                        }
-                        configureInterface();
+                    /*
+                     * The connection is fully configured as far as link-level
+                     * connectivity is concerned, but we may still need to obtain
+                     * an IP address.
+                     */
+                    if (wasDisconnectPending) {
+                        DetailedState saveState = getNetworkInfo().getDetailedState();
+                        handleDisconnectedState(DetailedState.DISCONNECTED);
+                        setDetailedStateInternal(saveState);
                     }
+                    configureInterface();
                     mLastBssid = result.BSSID;
                     mLastSsid = mWifiInfo.getSSID();
                     mLastNetworkId = result.networkId;