Merge "Removing unused code"
diff --git a/api/current.txt b/api/current.txt
index ca7b4e5..7d87425 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5400,6 +5400,7 @@
     field public static final int CONFIG_ORIENTATION = 128; // 0x80
     field public static final int CONFIG_SCREEN_LAYOUT = 256; // 0x100
     field public static final int CONFIG_SCREEN_SIZE = 1024; // 0x400
+    field public static final int CONFIG_SMALLEST_SCREEN_SIZE = 2048; // 0x800
     field public static final int CONFIG_TOUCHSCREEN = 8; // 0x8
     field public static final int CONFIG_UI_MODE = 512; // 0x200
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -5989,6 +5990,7 @@
     field public static final int SCREENLAYOUT_SIZE_XLARGE = 4; // 0x4
     field public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0; // 0x0
     field public static final int SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0
+    field public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0
     field public static final int TOUCHSCREEN_FINGER = 3; // 0x3
     field public static final int TOUCHSCREEN_NOTOUCH = 1; // 0x1
     field public static final int TOUCHSCREEN_STYLUS = 2; // 0x2
@@ -6015,6 +6017,7 @@
     field public int screenHeightDp;
     field public int screenLayout;
     field public int screenWidthDp;
+    field public int smallestScreenWidthDp;
     field public int touchscreen;
     field public int uiMode;
   }
@@ -9016,6 +9019,7 @@
     method public void close();
     method public int controlTransfer(int, int, int, int, byte[], int, int);
     method public int getFileDescriptor();
+    method public byte[] getRawDescriptors();
     method public java.lang.String getSerial();
     method public boolean releaseInterface(android.hardware.usb.UsbInterface);
     method public android.hardware.usb.UsbRequest requestWait();
@@ -10114,6 +10118,7 @@
     method public void setAuxiliaryOutputFile(java.lang.String);
     method public void setCamera(android.hardware.Camera);
     method public void setCaptureRate(double);
+    method public void setLocation(float, float);
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
@@ -24011,6 +24016,7 @@
     ctor public ExpandableListView(android.content.Context, android.util.AttributeSet, int);
     method public boolean collapseGroup(int);
     method public boolean expandGroup(int);
+    method public boolean expandGroup(int, boolean);
     method public android.widget.ExpandableListAdapter getExpandableListAdapter();
     method public long getExpandableListPosition(int);
     method public int getFlatListPosition(long);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 701c7ac..b0e4a86 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -30,11 +30,13 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
+import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -239,7 +241,7 @@
         String filter = nextArg();
 
         try {
-            List<PackageInfo> packages = mPm.getInstalledPackages(getFlags);
+            final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags);
 
             int count = packages.size();
             for (int p = 0 ; p < count ; p++) {
@@ -267,6 +269,22 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
+    private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags)
+            throws RemoteException {
+        final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
+        PackageInfo lastItem = null;
+        ParceledListSlice<PackageInfo> slice;
+
+        do {
+            final String lastKey = lastItem != null ? lastItem.packageName : null;
+            slice = pm.getInstalledPackages(flags, lastKey);
+            lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
+        } while (!slice.isLastSlice());
+
+        return packageInfos;
+    }
+
     /**
      * Lists all of the features supported by the current device.
      *
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 85918cf..4cff12f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -34,6 +34,7 @@
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
@@ -44,6 +45,7 @@
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
@@ -378,19 +380,41 @@
         throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public List<PackageInfo> getInstalledPackages(int flags) {
         try {
-            return mPM.getInstalledPackages(flags);
+            final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
+            PackageInfo lastItem = null;
+            ParceledListSlice<PackageInfo> slice;
+
+            do {
+                final String lastKey = lastItem != null ? lastItem.packageName : null;
+                slice = mPM.getInstalledPackages(flags, lastKey);
+                lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
+            } while (!slice.isLastSlice());
+
+            return packageInfos;
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public List<ApplicationInfo> getInstalledApplications(int flags) {
         try {
-            return mPM.getInstalledApplications(flags);
+            final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
+            ApplicationInfo lastItem = null;
+            ParceledListSlice<ApplicationInfo> slice;
+
+            do {
+                final String lastKey = lastItem != null ? lastItem.packageName : null;
+                slice = mPM.getInstalledApplications(flags, lastKey);
+                lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
+            } while (!slice.isLastSlice());
+
+            return applicationInfos;
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 64c437d..4285388 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -340,6 +340,12 @@
     public static final int CONFIG_SCREEN_SIZE = 0x0400;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the smallest screen size. Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_SMALLEST_SCREEN_SIZE = 0x0800;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the font scaling factor.  Set from the
      * {@link android.R.attr#configChanges} attribute.  This is
      * not a core resource configutation, but a higher-level value, so its
@@ -364,6 +370,7 @@
         0x0800, // SCREEN LAYOUT
         0x1000, // UI MODE
         0x0200, // SCREEN SIZE
+        0x2000, // SMALLEST SCREEN SIZE
     };
     /** @hide
      * Convert Java change bits to native.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 11cd446..37b6822 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -30,6 +30,7 @@
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.ProviderInfo;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
@@ -110,9 +111,21 @@
     List<ResolveInfo> queryIntentServices(in Intent intent,
             String resolvedType, int flags);
 
-    List<PackageInfo> getInstalledPackages(int flags);
+    /**
+     * This implements getInstalledPackages via a "last returned row"
+     * mechanism that is not exposed in the API. This is to get around the IPC
+     * limit that kicks in when flags are included that bloat up the data
+     * returned.
+     */
+    ParceledListSlice getInstalledPackages(int flags, in String lastRead);
 
-    List<ApplicationInfo> getInstalledApplications(int flags);
+    /**
+     * This implements getInstalledApplications via a "last returned row"
+     * mechanism that is not exposed in the API. This is to get around the IPC
+     * limit that kicks in when flags are included that bloat up the data
+     * returned.
+     */
+    ParceledListSlice getInstalledApplications(int flags, in String lastRead);
 
     /**
      * Retrieve all applications that are marked as persistent.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 18120ac..9ff324b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -396,7 +396,7 @@
             int cookie = assmgr.addAssetPath(mArchiveSourcePath);
             if (cookie != 0) {
                 res = new Resources(assmgr, metrics, null);
-                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                         Build.VERSION.RESOURCES_SDK_INT);
                 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
                 assetError = false;
@@ -596,7 +596,7 @@
         AssetManager assmgr = null;
         try {
             assmgr = new AssetManager();
-            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     Build.VERSION.RESOURCES_SDK_INT);
             int cookie = assmgr.addAssetPath(packageFilePath);
             parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
@@ -1943,7 +1943,8 @@
                     0);
             if (owner.applicationInfo.targetSdkVersion
                         < android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
-                a.info.configChanges |= ActivityInfo.CONFIG_SCREEN_SIZE;
+                a.info.configChanges |= ActivityInfo.CONFIG_SCREEN_SIZE
+                        | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
             }
             a.info.softInputMode = sa.getInt(
                     com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
diff --git a/core/java/android/content/pm/ParceledListSlice.aidl b/core/java/android/content/pm/ParceledListSlice.aidl
new file mode 100755
index 0000000..c02cc6a
--- /dev/null
+++ b/core/java/android/content/pm/ParceledListSlice.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable ParceledListSlice;
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
new file mode 100644
index 0000000..f3a98db4
--- /dev/null
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * Builds up a parcel that is discarded when written to another parcel or
+ * written to a list. This is useful for API that sends huge lists across a
+ * Binder that may be larger than the IPC limit.
+ *
+ * @hide
+ */
+public class ParceledListSlice<T extends Parcelable> implements Parcelable {
+    /*
+     * TODO get this number from somewhere else. For now set it to a quarter of
+     * the 1MB limit.
+     */
+    private static final int MAX_IPC_SIZE = 256 * 1024;
+
+    private Parcel mParcel;
+
+    private int mNumItems;
+
+    private boolean mIsLastSlice;
+
+    public ParceledListSlice() {
+        mParcel = Parcel.obtain();
+    }
+
+    private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) {
+        mParcel = p;
+        mNumItems = numItems;
+        mIsLastSlice = lastSlice;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Write this to another Parcel. Note that this discards the internal Parcel
+     * and should not be used anymore. This is so we can pass this to a Binder
+     * where we won't have a chance to call recycle on this.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mNumItems);
+        dest.writeInt(mIsLastSlice ? 1 : 0);
+
+        if (mNumItems > 0) {
+            final int parcelSize = mParcel.dataSize();
+            dest.writeInt(parcelSize);
+            dest.appendFrom(mParcel, 0, parcelSize);
+        }
+
+        mNumItems = 0;
+        mParcel.recycle();
+        mParcel = null;
+    }
+
+    /**
+     * Appends a parcel to this list slice.
+     *
+     * @param item Parcelable item to append to this list slice
+     * @return true when the list slice is full and should not be appended to
+     *         anymore
+     */
+    public boolean append(T item) {
+        if (mParcel == null) {
+            throw new IllegalStateException("ParceledListSlice has already been recycled");
+        }
+
+        item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE);
+        mNumItems++;
+
+        return mParcel.dataSize() > MAX_IPC_SIZE;
+    }
+
+    /**
+     * Populates a list and discards the internal state of the
+     * ParceledListSlice in the process. The instance should
+     * not be used anymore.
+     *
+     * @param list list to insert items from this slice.
+     * @param creator creator that knows how to unparcel the
+     *        target object type.
+     * @return the last item inserted into the list or null if none.
+     */
+    public T populateList(List<T> list, Creator<T> creator) {
+        mParcel.setDataPosition(0);
+
+        T item = null;
+        for (int i = 0; i < mNumItems; i++) {
+            item = creator.createFromParcel(mParcel);
+            list.add(item);
+        }
+
+        mParcel.recycle();
+        mParcel = null;
+
+        return item;
+    }
+
+    /**
+     * Sets whether this is the last list slice in the series.
+     *
+     * @param lastSlice
+     */
+    public void setLastSlice(boolean lastSlice) {
+        mIsLastSlice = lastSlice;
+    }
+
+    /**
+     * Returns whether this is the last slice in a series of slices.
+     *
+     * @return true if this is the last slice in the series.
+     */
+    public boolean isLastSlice() {
+        return mIsLastSlice;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static final Parcelable.Creator<ParceledListSlice> CREATOR =
+            new Parcelable.Creator<ParceledListSlice>() {
+        public ParceledListSlice createFromParcel(Parcel in) {
+            final int numItems = in.readInt();
+            final boolean lastSlice = in.readInt() == 1;
+
+            if (numItems > 0) {
+                final int parcelSize = in.readInt();
+
+                // Advance within this Parcel
+                int offset = in.dataPosition();
+                in.setDataPosition(offset + parcelSize);
+
+                Parcel p = Parcel.obtain();
+                p.setDataPosition(0);
+                p.appendFrom(in, offset, parcelSize);
+                p.setDataPosition(0);
+
+                return new ParceledListSlice(p, numItems, lastSlice);
+            } else {
+                return new ParceledListSlice();
+            }
+        }
+
+        public ParceledListSlice[] newArray(int size) {
+            return new ParceledListSlice[size];
+        }
+    };
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index be67e96..931cb18 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -652,8 +652,8 @@
     public native final void setConfiguration(int mcc, int mnc, String locale,
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode,
-            int majorVersion);
+            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
+            int screenLayout, int uiMode, int majorVersion);
 
     /**
      * Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 0de08f2..12ec258 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -259,6 +259,15 @@
      */
     public int screenHeightDp;
 
+    public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
+
+    /**
+     * The smallest screen size an application will see in normal operation.
+     * This is the smallest value of both screenWidthDp and screenHeightDp
+     * in both portrait and landscape.
+     */
+    public int smallestScreenWidthDp;
+
     /**
      * @hide Internal book-keeping.
      */
@@ -298,6 +307,7 @@
         uiMode = o.uiMode;
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
+        smallestScreenWidthDp = o.smallestScreenWidthDp;
         seq = o.seq;
     }
     
@@ -315,6 +325,56 @@
         } else {
             sb.append(" (no locale)");
         }
+        if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+            sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
+        } else {
+            sb.append("?swdp");
+        }
+        if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
+            sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
+        } else {
+            sb.append("?wdp");
+        }
+        if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
+            sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
+        } else {
+            sb.append("?hdp");
+        }
+        switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
+            case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
+            case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
+            case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
+            case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
+            case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
+            default: sb.append(" layoutSize=");
+                    sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
+        }
+        switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
+            case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
+            case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
+            case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
+            default: sb.append(" layoutLong=");
+                    sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
+        }
+        switch (orientation) {
+            case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
+            case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
+            case ORIENTATION_PORTRAIT: sb.append(" port"); break;
+            default: sb.append(" orien="); sb.append(orientation); break;
+        }
+        switch ((uiMode&UI_MODE_TYPE_MASK)) {
+            case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
+            case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
+            case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
+            case UI_MODE_TYPE_CAR: sb.append(" car"); break;
+            default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
+        }
+        switch ((uiMode&UI_MODE_NIGHT_MASK)) {
+            case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
+            case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
+            case UI_MODE_NIGHT_YES: sb.append(" night"); break;
+            default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
+        }
         switch (touchscreen) {
             case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
             case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
@@ -356,51 +416,6 @@
             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
             default: sb.append("/"); sb.append(navigationHidden); break;
         }
-        switch (orientation) {
-            case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
-            case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
-            case ORIENTATION_PORTRAIT: sb.append(" port"); break;
-            default: sb.append(" orien="); sb.append(orientation); break;
-        }
-        switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
-            case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
-            case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
-            case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
-            case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
-            case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
-            default: sb.append(" layoutSize=");
-                    sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
-        }
-        switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
-            case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
-            case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
-            case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
-            default: sb.append(" layoutLong=");
-                    sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
-        }
-        switch ((uiMode&UI_MODE_TYPE_MASK)) {
-            case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
-            case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
-            case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
-            case UI_MODE_TYPE_CAR: sb.append(" car"); break;
-            default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
-        }
-        switch ((uiMode&UI_MODE_NIGHT_MASK)) {
-            case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
-            case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
-            case UI_MODE_NIGHT_YES: sb.append(" night"); break;
-            default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
-        }
-        if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
-            sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
-        } else {
-            sb.append("?wdp");
-        }
-        if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
-            sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
-        } else {
-            sb.append("?hdp");
-        }
         if (seq != 0) {
             sb.append(" s.");
             sb.append(seq);
@@ -428,6 +443,7 @@
         uiMode = UI_MODE_TYPE_UNDEFINED;
         screenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
+        smallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
         seq = 0;
     }
 
@@ -531,6 +547,11 @@
             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
             screenHeightDp = delta.screenHeightDp;
         }
+        if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+                && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+            changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+            smallestScreenWidthDp = delta.smallestScreenWidthDp;
+        }
         
         if (delta.seq != 0) {
             seq = delta.seq;
@@ -564,7 +585,9 @@
      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
      * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
-     * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}.
+     * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
+     * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
+     * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
      */
     public int diff(Configuration delta) {
         int changed = 0;
@@ -625,6 +648,10 @@
                 && screenHeightDp != delta.screenHeightDp) {
             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
         }
+        if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+                && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+            changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+        }
         
         return changed;
     }
@@ -708,6 +735,7 @@
         dest.writeInt(uiMode);
         dest.writeInt(screenWidthDp);
         dest.writeInt(screenHeightDp);
+        dest.writeInt(smallestScreenWidthDp);
         dest.writeInt(seq);
     }
 
@@ -731,6 +759,7 @@
         uiMode = source.readInt();
         screenWidthDp = source.readInt();
         screenHeightDp = source.readInt();
+        smallestScreenWidthDp = source.readInt();
         seq = source.readInt();
     }
     
@@ -795,6 +824,8 @@
         n = this.screenWidthDp - that.screenWidthDp;
         if (n != 0) return n;
         n = this.screenHeightDp - that.screenHeightDp;
+        if (n != 0) return n;
+        n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
         //if (n != 0) return n;
         return n;
     }
@@ -830,6 +861,7 @@
         result = 31 * result + uiMode;
         result = 31 * result + screenWidthDp;
         result = 31 * result + screenHeightDp;
+        result = 31 * result + smallestScreenWidthDp;
         return result;
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 540f704..a072e94 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1458,6 +1458,7 @@
                     mConfiguration.touchscreen,
                     (int)(mMetrics.density*160), mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
+                    mConfiguration.smallestScreenWidthDp,
                     mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
                     mConfiguration.screenLayout, mConfiguration.uiMode,
                     Build.VERSION.RESOURCES_SDK_INT);
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index a153c0b..b536490 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -69,6 +69,17 @@
     }
 
     /**
+     * Returns the raw USB descriptors for the device.
+     * This can be used to access descriptors not supported directly
+     * via the higher level APIs.
+     *
+     * @return raw USB descriptors
+     */
+    public byte[] getRawDescriptors() {
+        return native_get_desc();
+    }
+
+    /**
      * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}.
      * This must be done before sending or receiving data on any
      * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface.
@@ -160,6 +171,7 @@
     private native boolean native_open(String deviceName, FileDescriptor pfd);
     private native void native_close();
     private native int native_get_fd();
+    private native byte[] native_get_desc();
     private native boolean native_claim_interface(int interfaceID, boolean force);
     private native boolean native_release_interface(int interfaceID);
     private native int native_control_request(int requestType, int request, int value,
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 61acf2b..19894a0 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -68,7 +68,8 @@
             mLinkAddresses = source.getLinkAddresses();
             mDnses = source.getDnses();
             mRoutes = source.getRoutes();
-            mHttpProxy = new ProxyProperties(source.getHttpProxy());
+            mHttpProxy = (source.getHttpProxy() == null)  ?
+                null : new ProxyProperties(source.getHttpProxy());
         }
     }
 
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index c5288c4..8e5ddda 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -140,6 +140,33 @@
         }
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+
+        if (!(obj instanceof RouteInfo)) return false;
+
+        RouteInfo target = (RouteInfo) obj;
+
+        boolean sameDestination = ( mDestination == null) ?
+                target.getDestination() == null
+                : mDestination.equals(target.getDestination());
+
+        boolean sameAddress = (mGateway == null) ?
+                target.getGateway() == null
+                : mGateway.equals(target.getGateway());
+
+        return sameDestination && sameAddress
+            && mIsDefault == target.mIsDefault;
+    }
+
+    @Override
+    public int hashCode() {
+        return (mDestination == null ? 0 : mDestination.hashCode())
+            + (mGateway == null ? 0 :mGateway.hashCode())
+            + (mIsDefault ? 3 : 7);
+    }
+
     public static final Creator<RouteInfo> CREATOR =
         new Creator<RouteInfo>() {
         public RouteInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 68caa53..d5f573c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -49,8 +49,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pool;
@@ -8496,6 +8494,8 @@
         }
         jumpDrawablesToCurrentState();
 
+        // We are supposing here that the parent directionality will be resolved before its children
+        // View horizontalDirection public attribute resolution to an internal var.
         // Resolving the layout direction. LTR is set initially.
         mPrivateFlags2 &= ~RESOLVED_LAYOUT_RTL;
         switch (getHorizontalDirection()) {
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 1534099..4aa8727 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -92,21 +92,6 @@
     public static final boolean TRACE_RECYCLER = false;
 
     /**
-     * Enables or disables motion events tracing. Any invoker of
-     * {@link #trace(View, MotionEvent, MotionEventTraceType)} should first check
-     * that this value is set to true as not to affect performance.
-     * 
-     * @hide
-     */
-    public static final boolean TRACE_MOTION_EVENTS = false;
-
-    /**
-     * The system property of dynamic switch for capturing view information
-     * when it is set, we dump interested fields and methods for the view on focus
-     */
-    static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview";
-
-    /**
      * The system property of dynamic switch for capturing event information
      * when it is set, we log key events, touch/motion and trackball events
      */
@@ -170,12 +155,6 @@
     @Debug.DebugProperty
     public static boolean consistencyCheckEnabled = false;
 
-    static {
-        if (false) {        
-	        Debug.setFieldsOn(ViewDebug.class, true);
-	    }
-    }
-
     /**
      * This annotation can be used to mark fields and methods to be dumped by
      * the view server. Only non-void methods with no arguments can be annotated
@@ -424,21 +403,6 @@
     private static String sRecyclerTracePrefix;
 
     /**
-     * Defines the type of motion events trace to output to the motion events traces file.
-     * 
-     * @hide
-     */
-    public enum MotionEventTraceType {
-        DISPATCH,
-        ON_INTERCEPT,
-        ON_TOUCH
-    }
-
-    private static BufferedWriter sMotionEventTraces;
-    private static ViewAncestor sMotionEventRoot;
-    private static String sMotionEventTracePrefix;
-
-    /**
      * Returns the number of instanciated Views.
      *
      * @return The number of Views instanciated in the current process.
@@ -574,6 +538,7 @@
         recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".traces");
         try {
             if (recyclerDump.exists()) {
+                //noinspection ResultOfMethodCallIgnored
                 recyclerDump.delete();
             }
             final FileOutputStream file = new FileOutputStream(recyclerDump);
@@ -732,146 +697,6 @@
         sHierarhcyRoot = null;
     }
 
-    /**
-     * Outputs a trace to the currently opened traces file. The trace contains the class name
-     * and instance's hashcode of the specified view as well as the supplied trace type.
-     *
-     * @param view the view to trace
-     * @param event the event of the trace
-     * @param type the type of the trace
-     * 
-     * @hide
-     */
-    public static void trace(View view, MotionEvent event, MotionEventTraceType type) {
-        if (sMotionEventTraces == null) {
-            return;
-        }
-
-        try {
-            sMotionEventTraces.write(type.name());
-            sMotionEventTraces.write(' ');
-            sMotionEventTraces.write(event.getAction());
-            sMotionEventTraces.write(' ');
-            sMotionEventTraces.write(view.getClass().getName());
-            sMotionEventTraces.write('@');
-            sMotionEventTraces.write(Integer.toHexString(view.hashCode()));
-            sHierarchyTraces.newLine();
-        } catch (IOException e) {
-            Log.w("View", "Error while dumping trace of event " + event + " for view " + view);
-        }
-    }
-
-    /**
-     * Starts tracing the motion events for the hierarchy of the specificy view.
-     * The trace is identified by a prefix, used to build the traces files names:
-     * <code>/EXTERNAL/motion-events/PREFIX.traces</code> and
-     * <code>/EXTERNAL/motion-events/PREFIX.tree</code>.
-     *
-     * Only one view hierarchy can be traced at the same time. After calling this method, any
-     * other invocation will result in a <code>IllegalStateException</code> unless
-     * {@link #stopMotionEventTracing()} is invoked before.
-     *
-     * Calling this method creates the file <code>/EXTERNAL/motion-events/PREFIX.traces</code>
-     * containing all the traces (or method calls) relative to the specified view's hierarchy.
-     *
-     * This method will return immediately if TRACE_HIERARCHY is false.
-     *
-     * @param prefix the traces files name prefix
-     * @param view the view whose hierarchy must be traced
-     *
-     * @see #stopMotionEventTracing()
-     * @see #trace(View, MotionEvent, android.view.ViewDebug.MotionEventTraceType)
-     * 
-     * @hide 
-     */
-    public static void startMotionEventTracing(String prefix, View view) {
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        if (!TRACE_MOTION_EVENTS) {
-            return;
-        }
-
-        if (sMotionEventRoot != null) {
-            throw new IllegalStateException("You must call stopMotionEventTracing() before running" +
-                " a new trace!");
-        }
-
-        File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "motion-events/");
-        //noinspection ResultOfMethodCallIgnored
-        hierarchyDump.mkdirs();
-
-        hierarchyDump = new File(hierarchyDump, prefix + ".traces");
-        sMotionEventTracePrefix = prefix;
-
-        try {
-            sMotionEventTraces = new BufferedWriter(new FileWriter(hierarchyDump), 32 * 1024);
-        } catch (IOException e) {
-            Log.e("View", "Could not dump view hierarchy");
-            return;
-        }
-
-        sMotionEventRoot = (ViewAncestor) view.getRootView().getParent();
-    }
-
-    /**
-     * Stops the current motion events tracing. This method closes the file
-     * <code>/EXTERNAL/motion-events/PREFIX.traces</code>.
-     *
-     * Calling this method creates the file <code>/EXTERNAL/motion-events/PREFIX.tree</code>
-     * containing the view hierarchy of the view supplied to
-     * {@link #startMotionEventTracing(String, View)}.
-     *
-     * This method will return immediately if TRACE_HIERARCHY is false.
-     *
-     * @see #startMotionEventTracing(String, View) 
-     * @see #trace(View, MotionEvent, android.view.ViewDebug.MotionEventTraceType) 
-     * 
-     * @hide
-     */
-    public static void stopMotionEventTracing() {
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        if (!TRACE_MOTION_EVENTS) {
-            return;
-        }
-
-        if (sMotionEventRoot == null || sMotionEventTraces == null) {
-            throw new IllegalStateException("You must call startMotionEventTracing() before" +
-                " stopMotionEventTracing()!");
-        }
-
-        try {
-            sMotionEventTraces.close();
-        } catch (IOException e) {
-            Log.e("View", "Could not write view traces");
-        }
-        sMotionEventTraces = null;
-
-        File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "motion-events/");
-        //noinspection ResultOfMethodCallIgnored
-        hierarchyDump.mkdirs();
-        hierarchyDump = new File(hierarchyDump, sMotionEventTracePrefix + ".tree");
-
-        BufferedWriter out;
-        try {
-            out = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024);
-        } catch (IOException e) {
-            Log.e("View", "Could not dump view hierarchy");
-            return;
-        }
-
-        View view = sMotionEventRoot.getView();
-        if (view instanceof ViewGroup) {
-            ViewGroup group = (ViewGroup) view;
-            dumpViewHierarchy(group, out, 0);
-            try {
-                out.close();
-            } catch (IOException e) {
-                Log.e("View", "Could not dump view hierarchy");
-            }
-        }
-
-        sHierarhcyRoot = null;
-    }
-
     static void dispatchCommand(View view, String command, String parameters,
             OutputStream clientStream) throws IOException {
 
@@ -1069,8 +894,10 @@
                 try {
                     T[] data = operation.pre();
                     long start = Debug.threadCpuTimeNanos();
+                    //noinspection unchecked
                     operation.run(data);
                     duration[0] = Debug.threadCpuTimeNanos() - start;
+                    //noinspection unchecked
                     operation.post(data);
                 } finally {
                     latch.countDown();
@@ -1201,12 +1028,7 @@
                         cache[0] = captureView.createSnapshot(
                                 Bitmap.Config.ARGB_8888, 0, skpiChildren);
                     } catch (OutOfMemoryError e) {
-                        try {
-                            cache[0] = captureView.createSnapshot(
-                                    Bitmap.Config.ARGB_4444, 0, skpiChildren);
-                        } catch (OutOfMemoryError e2) {
-                            Log.w("View", "Out of memory for bitmap");
-                        }
+                        Log.w("View", "Out of memory for bitmap");
                     } finally {
                         latch.countDown();
                     }
@@ -1316,7 +1138,6 @@
         }
 
         final HashMap<Class<?>, Field[]> map = sFieldsForClasses;
-        final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations;
 
         Field[] fields = map.get(klass);
         if (fields != null) {
@@ -1332,7 +1153,7 @@
             if (field.isAnnotationPresent(ExportedProperty.class)) {
                 field.setAccessible(true);
                 foundFields.add(field);
-                annotations.put(field, field.getAnnotation(ExportedProperty.class));
+                sAnnotations.put(field, field.getAnnotation(ExportedProperty.class));
             }
         }
 
@@ -1351,7 +1172,6 @@
         }
 
         final HashMap<Class<?>, Method[]> map = sMethodsForClasses;
-        final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations;
 
         Method[] methods = map.get(klass);
         if (methods != null) {
@@ -1369,7 +1189,7 @@
                     method.getReturnType() != Void.class) {
                 method.setAccessible(true);
                 foundMethods.add(method);
-                annotations.put(method, method.getAnnotation(ExportedProperty.class));
+                sAnnotations.put(method, method.getAnnotation(ExportedProperty.class));
             }
         }
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 5a418f3..4e52e40 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -466,16 +466,34 @@
     public int getMaxWallpaperLayer();
     
     /**
-     * Return the display width available after excluding the window
-     * decor.
+     * Return the display width available after excluding any screen
+     * decorations that can never be removed.  That is, system bar or
+     * button bar.
      */
-    public int getNonDecorDisplayWidth(int fullWidth);
+    public int getNonDecorDisplayWidth(int rotation, int fullWidth);
 
     /**
-     * Return the display height available after excluding the screen
-     * decor.
+     * Return the display height available after excluding any screen
+     * decorations that can never be removed.  That is, system bar or
+     * button bar.
      */
-    public int getNonDecorDisplayHeight(int fullHeight);
+    public int getNonDecorDisplayHeight(int rotation, int fullHeight);
+
+    /**
+     * Return the available screen width that we should report for the
+     * configuration.  This must be no larger than
+     * {@link #getNonDecorDisplayWidth(int, int)}; it may be smaller than
+     * that to account for more transient decoration like a status bar.
+     */
+    public int getConfigDisplayWidth(int rotation, int fullWidth);
+
+    /**
+     * Return the available screen height that we should report for the
+     * configuration.  This must be no larger than
+     * {@link #getNonDecorDisplayHeight(int, int)}; it may be smaller than
+     * that to account for more transient decoration like a status bar.
+     */
+    public int getConfigDisplayHeight(int rotation, int fullHeight);
 
     /**
      * Return whether the given window should forcibly hide everything
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index f862368..ead9b4f 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -599,12 +599,35 @@
      *         was already expanded, this will return false)
      */
     public boolean expandGroup(int groupPos) {
-        boolean retValue = mConnector.expandGroup(groupPos);
+       return expandGroup(groupPos, false);
+    }
+
+    /**
+     * Expand a group in the grouped list view
+     *
+     * @param groupPos the group to be expanded
+     * @param animate true if the expanding group should be animated in
+     * @return True if the group was expanded, false otherwise (if the group
+     *         was already expanded, this will return false)
+     */
+    public boolean expandGroup(int groupPos, boolean animate) {
+        PositionMetadata pm = mConnector.getFlattenedPos(ExpandableListPosition.obtain(
+                ExpandableListPosition.GROUP, groupPos, -1, -1));
+        boolean retValue = mConnector.expandGroup(pm);
 
         if (mOnGroupExpandListener != null) {
             mOnGroupExpandListener.onGroupExpand(groupPos);
         }
-        
+
+        if (animate) {
+            final int groupFlatPos = pm.position.flatListPos;
+
+            final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount();
+            smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos),
+                    shiftedGroupPosition);
+        }
+        pm.recycle();
+
         return retValue;
     }
     
diff --git a/core/jni/android_content_res_Configuration.cpp b/core/jni/android_content_res_Configuration.cpp
index 95b18ea..246e3bd 100644
--- a/core/jni/android_content_res_Configuration.cpp
+++ b/core/jni/android_content_res_Configuration.cpp
@@ -38,6 +38,9 @@
     jfieldID navigationHidden;
     jfieldID orientation;
     jfieldID uiMode;
+    jfieldID screenWidthDp;
+    jfieldID screenHeightDp;
+    jfieldID smallestScreenWidthDp;
 } gConfigurationClassInfo;
 
 void android_Configuration_getFromJava(
@@ -60,6 +63,11 @@
 
     out->orientation = env->GetIntField(clazz, gConfigurationClassInfo.orientation);
     out->uiMode = env->GetIntField(clazz, gConfigurationClassInfo.uiMode);
+
+    out->screenWidthDp = env->GetIntField(clazz, gConfigurationClassInfo.screenWidthDp);
+    out->screenHeightDp = env->GetIntField(clazz, gConfigurationClassInfo.screenHeightDp);
+    out->smallestScreenWidthDp = env->GetIntField(clazz,
+            gConfigurationClassInfo.smallestScreenWidthDp);
 }
 
 /*
@@ -108,6 +116,12 @@
             "orientation", "I");
     GET_FIELD_ID(gConfigurationClassInfo.uiMode, clazz,
             "uiMode", "I");
+    GET_FIELD_ID(gConfigurationClassInfo.screenWidthDp, clazz,
+            "screenWidthDp", "I");
+    GET_FIELD_ID(gConfigurationClassInfo.screenHeightDp, clazz,
+            "screenHeightDp", "I");
+    GET_FIELD_ID(gConfigurationClassInfo.smallestScreenWidthDp, clazz,
+            "smallestScreenWidthDp", "I");
 
     return AndroidRuntime::registerNativeMethods(env, "android/content/res/Configuration", gMethods,
             NELEM(gMethods));
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index 4d73bf3..68be9e1 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -83,6 +83,27 @@
     return usb_device_get_fd(device);
 }
 
+static jbyteArray
+android_hardware_UsbDeviceConnection_get_desc(JNIEnv *env, jobject thiz)
+{
+    char buffer[16384];
+    int fd = android_hardware_UsbDeviceConnection_get_fd(env, thiz);
+    if (fd < 0) return NULL;
+    lseek(fd, 0, SEEK_SET);
+    int length = read(fd, buffer, sizeof(buffer));
+    if (length < 0) return NULL;
+
+    jbyteArray ret = env->NewByteArray(length);
+    if (ret) {
+        jbyte* bytes = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
+        if (bytes) {
+            memcpy(bytes, buffer, length);
+            env->ReleasePrimitiveArrayCritical(ret, bytes, 0);
+        }
+    }
+    return ret;
+}
+
 static jboolean
 android_hardware_UsbDeviceConnection_claim_interface(JNIEnv *env, jobject thiz,
         int interfaceID, jboolean force)
@@ -211,6 +232,7 @@
                                         (void *)android_hardware_UsbDeviceConnection_open},
     {"native_close",            "()V",  (void *)android_hardware_UsbDeviceConnection_close},
     {"native_get_fd",           "()I",  (void *)android_hardware_UsbDeviceConnection_get_fd},
+    {"native_get_desc",         "()[B", (void *)android_hardware_UsbDeviceConnection_get_desc},
     {"native_claim_interface",  "(IZ)Z",(void *)android_hardware_UsbDeviceConnection_claim_interface},
     {"native_release_interface","(I)Z", (void *)android_hardware_UsbDeviceConnection_release_interface},
     {"native_control_request",  "(IIII[BII)I",
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index b0e92e4..4f8f1af 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -510,6 +510,7 @@
                                                           jint keyboard, jint keyboardHidden,
                                                           jint navigation,
                                                           jint screenWidth, jint screenHeight,
+                                                          jint smallestScreenWidthDp,
                                                           jint screenWidthDp, jint screenHeightDp,
                                                           jint screenLayout, jint uiMode,
                                                           jint sdkVersion)
@@ -534,6 +535,7 @@
     config.navigation = (uint8_t)navigation;
     config.screenWidth = (uint16_t)screenWidth;
     config.screenHeight = (uint16_t)screenHeight;
+    config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
     config.screenWidthDp = (uint16_t)screenWidthDp;
     config.screenHeightDp = (uint16_t)screenHeightDp;
     config.screenLayout = (uint8_t)screenLayout;
@@ -1646,7 +1648,7 @@
         (void*) android_content_AssetManager_setLocale },
     { "getLocales",      "()[Ljava/lang/String;",
         (void*) android_content_AssetManager_getLocales },
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIII)V",
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
     { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*) android_content_AssetManager_getResourceIdentifier },
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
index da36b67..55eb145 100644
--- a/core/res/res/values-large/dimens.xml
+++ b/core/res/res/values-large/dimens.xml
@@ -24,10 +24,6 @@
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
 
-    <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
-    <!-- Margin for permanent screen decorations at the bottom. -->
-    <dimen name="screen_margin_bottom">48dip</dimen>
-
     <!-- Default height of a key in the password keyboard for alpha -->
     <dimen name="password_keyboard_key_height_alpha">75dip</dimen>
     <!-- Default height of a key in the password keyboard for numeric -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 625afff..6b7c2a6 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -590,11 +590,21 @@
         <!-- The global user interface mode has changed.  For example,
              going in or out of car mode, night mode changing, etc. -->
         <flag name="uiMode" value="0x0200" />
+        <!-- The current available screen size has changed.  If applications don't
+             target at least {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}
+             then the activity will always handle this itself (the change
+             will not result in a restart).  This represents a change in the
+             currently available size, so will change when the user switches
+             between landscape and portrait. -->
+        <flag name="screenSize" value="0x0400" />
         <!-- The physical screen size has changed.  If applications don't
              target at least {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}
              then the activity will always handle this itself (the change
-             will not result in a restart). -->
-        <flag name="screenSize" value="0x0400" />
+             will not result in a restart).  This represents a change in size
+             regardless of orientation, so will only change when the actual
+             physical screen size has changed such as switching to an external
+             display. -->
+        <flag name="smallestScreenSize" value="0x0800" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e405f20..3f4010b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -38,8 +38,6 @@
     <dimen name="status_bar_content_number_size">48sp</dimen>
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
-    <!-- Margin for permanent screen decorations at the bottom. -->
-    <dimen name="screen_margin_bottom">0dip</dimen>
     <!-- Size of the fastscroll hint letter -->
     <dimen name="fastscroll_overlay_size">104dp</dimen>
     <!-- Width of the fastscroll thumb -->
diff --git a/docs/html/guide/appendix/install-location.jd b/docs/html/guide/appendix/install-location.jd
index 7f96809..617f4fc 100644
--- a/docs/html/guide/appendix/install-location.jd
+++ b/docs/html/guide/appendix/install-location.jd
@@ -171,6 +171,11 @@
     <dd>The system delivers the {@link android.content.Intent#ACTION_BOOT_COMPLETED} broadcast
 before the external storage is mounted to the device. If your application is installed on the
 external storage, it can never receive this broadcast.</dd>
+  <dt>Copy Protection</dt>
+    <dd>Your application cannot be installed to a device's SD card if it uses Android Market's 
+      Copy Protection feature. However, if you use Android Market's 
+      <a href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a> instead, your 
+      application <em>can</em> be installed to internal or external storage, including SD cards.</dd>
 </dl>
 
 <p>If your application uses any of the features listed above, you <strong>should not</strong> allow
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
index a9b182e..d89a8ca 100644
--- a/docs/html/guide/publishing/licensing.jd
+++ b/docs/html/guide/publishing/licensing.jd
@@ -263,15 +263,15 @@
 you won't be able to upload a new version that uses licensing.</li>
 </ul>
 
-<h4>Replacement for copy protection</h4>
+<h4>Replacement for Copy Protection</h4>
 
 <p>Android Market Licensing is a flexible, secure mechanism for controlling
-access to your applications. It effectively replaces the copy-protection
+access to your applications. It effectively replaces the Copy Protection
 mechanism offered on Android Market and gives you wider distribution
 potential for your applications. </p>
 
 <ul>
-<li>A limitation of the legacy copy-protection mechanism on Android Market is
+<li>A limitation of the legacy Copy Protection mechanism on Android Market is
 that applications using it can be installed only on compatible devices that
 provide a secure internal storage environment. For example, a copy-protected
 application cannot be downloaded from Market to a device that provides root
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index a8125b3..598e88f 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -141,9 +141,14 @@
 </tr>
 </table>
 
+<p class="caution"><strong>Caution:</strong> If your application uses the Android Market's Copy 
+  Protection feature, it cannot be installed to a device's SD card. However, if you use Android 
+  Market's <a href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a> instead, 
+  your application <em>can</em> be installed to internal or external storage, including SD cards.</p>
+
 <p class="note"><strong>Note:</strong> By default, your application will be installed on the
-internal storage and cannot be installed on the external storage unless you define this attribute
-to be either "{@code auto}" or "{@code preferExternal}".</p>
+  internal storage and cannot be installed on the external storage unless you define this attribute
+  to be either "{@code auto}" or "{@code preferExternal}".</p>
 
 <p>When an application is installed on the external storage:</p>
 <ul>
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index f355087..4126225 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -51,7 +51,6 @@
 }
 
 // ---------------------------------------------------------------------------
-
 class ReferenceMover;
 class ReferenceConverterBase {
 public:
@@ -120,7 +119,14 @@
 protected:
                             RefBase();
     virtual                 ~RefBase();
-    
+
+    // called when the last reference goes away. this is responsible for
+    // calling the destructor. The default implementation just does
+    // "delete this;".
+    // Make sure to never acquire a strong reference from this function. The
+    // same restrictions than for destructors apply.
+    virtual void            destroy() const;
+
     //! Flags for extendObjectLifetime()
     enum {
         OBJECT_LIFETIME_WEAK    = 0x0001,
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 173412e..9e4e132 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -966,8 +966,7 @@
         struct {
             uint8_t screenLayout;
             uint8_t uiMode;
-            uint8_t screenConfigPad1;
-            uint8_t screenConfigPad2;
+            uint16_t smallestScreenWidthDp;
         };
         uint32_t screenConfig;
     };
@@ -1000,6 +999,7 @@
         screenHeight = dtohs(screenHeight);
         sdkVersion = dtohs(sdkVersion);
         minorVersion = dtohs(minorVersion);
+        smallestScreenWidthDp = dtohs(smallestScreenWidthDp);
         screenWidthDp = dtohs(screenWidthDp);
         screenHeightDp = dtohs(screenHeightDp);
     }
@@ -1013,6 +1013,7 @@
         screenHeight = htods(screenHeight);
         sdkVersion = htods(sdkVersion);
         minorVersion = htods(minorVersion);
+        smallestScreenWidthDp = htods(smallestScreenWidthDp);
         screenWidthDp = htods(screenWidthDp);
         screenHeightDp = htods(screenHeightDp);
     }
@@ -1034,6 +1035,8 @@
         if (diff != 0) return diff;
         diff = (int32_t)(uiMode - o.uiMode);
         if (diff != 0) return diff;
+        diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp);
+        if (diff != 0) return diff;
         diff = (int32_t)(screenSizeDp - o.screenSizeDp);
         return (int)diff;
     }
@@ -1052,6 +1055,7 @@
         CONFIG_ORIENTATION = ACONFIGURATION_ORIENTATION,
         CONFIG_DENSITY = ACONFIGURATION_DENSITY,
         CONFIG_SCREEN_SIZE = ACONFIGURATION_SCREEN_SIZE,
+        CONFIG_SMALLEST_SCREEN_SIZE = ACONFIGURATION_SMALLEST_SCREEN_SIZE,
         CONFIG_VERSION = ACONFIGURATION_VERSION,
         CONFIG_SCREEN_LAYOUT = ACONFIGURATION_SCREEN_LAYOUT,
         CONFIG_UI_MODE = ACONFIGURATION_UI_MODE
@@ -1075,6 +1079,7 @@
         if (version != o.version) diffs |= CONFIG_VERSION;
         if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT;
         if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
+        if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
         if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
         return diffs;
     }
@@ -1109,14 +1114,10 @@
             }
         }
 
-        if (screenLayout || o.screenLayout) {
-            if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0) {
-                if (!(screenLayout & MASK_SCREENSIZE)) return false;
-                if (!(o.screenLayout & MASK_SCREENSIZE)) return true;
-            }
-            if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0) {
-                if (!(screenLayout & MASK_SCREENLONG)) return false;
-                if (!(o.screenLayout & MASK_SCREENLONG)) return true;
+        if (smallestScreenWidthDp || o.smallestScreenWidthDp) {
+            if (smallestScreenWidthDp != o.smallestScreenWidthDp) {
+                if (!smallestScreenWidthDp) return false;
+                if (!o.smallestScreenWidthDp) return true;
             }
         }
 
@@ -1132,6 +1133,17 @@
             }
         }
 
+        if (screenLayout || o.screenLayout) {
+            if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0) {
+                if (!(screenLayout & MASK_SCREENSIZE)) return false;
+                if (!(o.screenLayout & MASK_SCREENSIZE)) return true;
+            }
+            if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0) {
+                if (!(screenLayout & MASK_SCREENLONG)) return false;
+                if (!(o.screenLayout & MASK_SCREENLONG)) return true;
+            }
+        }
+
         if (orientation != o.orientation) {
             if (!orientation) return false;
             if (!o.orientation) return true;
@@ -1238,6 +1250,37 @@
                 }
             }
 
+            if (smallestScreenWidthDp || o.smallestScreenWidthDp) {
+                // The configuration closest to the actual size is best.
+                // We assume that larger configs have already been filtered
+                // out at this point.  That means we just want the largest one.
+                return smallestScreenWidthDp >= o.smallestScreenWidthDp;
+            }
+
+            if (screenSizeDp || o.screenSizeDp) {
+                // "Better" is based on the sum of the difference between both
+                // width and height from the requested dimensions.  We are
+                // assuming the invalid configs (with smaller dimens) have
+                // already been filtered.  Note that if a particular dimension
+                // is unspecified, we will end up with a large value (the
+                // difference between 0 and the requested dimension), which is
+                // good since we will prefer a config that has specified a
+                // dimension value.
+                int myDelta = 0, otherDelta = 0;
+                if (requested->screenWidthDp) {
+                    myDelta += requested->screenWidthDp - screenWidthDp;
+                    otherDelta += requested->screenWidthDp - o.screenWidthDp;
+                }
+                if (requested->screenHeightDp) {
+                    myDelta += requested->screenHeightDp - screenHeightDp;
+                    otherDelta += requested->screenHeightDp - o.screenHeightDp;
+                }
+                //LOGI("Comparing this %dx%d to other %dx%d in %dx%d: myDelta=%d otherDelta=%d",
+                //    screenWidthDp, screenHeightDp, o.screenWidthDp, o.screenHeightDp,
+                //    requested->screenWidthDp, requested->screenHeightDp, myDelta, otherDelta);
+                return (myDelta <= otherDelta);
+            }
+
             if (screenLayout || o.screenLayout) {
                 if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0
                         && (requested->screenLayout & MASK_SCREENSIZE)) {
@@ -1270,30 +1313,6 @@
                 }
             }
 
-            if (screenSizeDp || o.screenSizeDp) {
-                // Better is based on the sum of the difference between both
-                // width and height from the requested dimensions.  We are
-                // assuming the invalid configs (with smaller dimens) have
-                // already been filtered.  Note that if a particular dimension
-                // is unspecified, we will end up with a large value (the
-                // difference between 0 and the requested dimension), which is
-                // good since we will prefer a config that has specified a
-                // dimension value.
-                int myDelta = 0, otherDelta = 0;
-                if (requested->screenWidthDp) {
-                    myDelta += requested->screenWidthDp - screenWidthDp;
-                    otherDelta += requested->screenWidthDp - o.screenWidthDp;
-                }
-                if (requested->screenHeightDp) {
-                    myDelta += requested->screenHeightDp - screenHeightDp;
-                    otherDelta += requested->screenHeightDp - o.screenHeightDp;
-                }
-                //LOGI("Comparing this %dx%d to other %dx%d in %dx%d: myDelta=%d otherDelta=%d",
-                //    screenWidthDp, screenHeightDp, o.screenWidthDp, o.screenHeightDp,
-                //    requested->screenWidthDp, requested->screenHeightDp, myDelta, otherDelta);
-                return (myDelta <= otherDelta);
-            }
-
             if ((orientation != o.orientation) && requested->orientation) {
                 return (orientation);
             }
@@ -1388,14 +1407,24 @@
             }
 
             if (screenSize || o.screenSize) {
-                if ((screenWidth != o.screenWidth) && requested->screenWidth) {
-                    return (screenWidth);
+                // "Better" is based on the sum of the difference between both
+                // width and height from the requested dimensions.  We are
+                // assuming the invalid configs (with smaller sizes) have
+                // already been filtered.  Note that if a particular dimension
+                // is unspecified, we will end up with a large value (the
+                // difference between 0 and the requested dimension), which is
+                // good since we will prefer a config that has specified a
+                // size value.
+                int myDelta = 0, otherDelta = 0;
+                if (requested->screenWidth) {
+                    myDelta += requested->screenWidth - screenWidth;
+                    otherDelta += requested->screenWidth - o.screenWidth;
                 }
-
-                if ((screenHeight != o.screenHeight) &&
-                        requested->screenHeight) {
-                    return (screenHeight);
+                if (requested->screenHeight) {
+                    myDelta += requested->screenHeight - screenHeight;
+                    otherDelta += requested->screenHeight - o.screenHeight;
                 }
+                return (myDelta <= otherDelta);
             }
 
             if (version || o.version) {
@@ -1476,15 +1505,20 @@
                     && uiModeNight != setUiModeNight) {
                 return false;
             }
+
+            if (settings.smallestScreenWidthDp != 0 && smallestScreenWidthDp != 0
+                    && smallestScreenWidthDp > settings.smallestScreenWidthDp) {
+                return false;
+            }
         }
         if (screenSizeDp != 0) {
             if (settings.screenWidthDp != 0 && screenWidthDp != 0
-                && screenWidthDp > settings.screenWidthDp) {
+                    && screenWidthDp > settings.screenWidthDp) {
                 //LOGI("Filtering out width %d in requested %d", screenWidthDp, settings.screenWidthDp);
                 return false;
             }
             if (settings.screenHeightDp != 0 && screenHeightDp != 0
-                && screenHeightDp > settings.screenHeightDp) {
+                    && screenHeightDp > settings.screenHeightDp) {
                 //LOGI("Filtering out height %d in requested %d", screenHeightDp, settings.screenHeightDp);
                 return false;
             }
@@ -1531,11 +1565,11 @@
         }
         if (screenSize != 0) {
             if (settings.screenWidth != 0 && screenWidth != 0
-                && screenWidth != settings.screenWidth) {
+                && screenWidth > settings.screenWidth) {
                 return false;
             }
             if (settings.screenHeight != 0 && screenHeight != 0
-                && screenHeight != settings.screenHeight) {
+                && screenHeight > settings.screenHeight) {
                 return false;
             }
         }
@@ -1568,13 +1602,13 @@
     String8 toString() const {
         char buf[200];
         sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=%d touch=%d dens=%d "
-                "kbd=%d nav=%d input=%d ssz=%dx%d %ddp x %ddp sz=%d long=%d "
+                "kbd=%d nav=%d input=%d ssz=%dx%d sw%ddp w%ddp h%ddp sz=%d long=%d "
                 "ui=%d night=%d vers=%d.%d",
                 mcc, mnc,
                 language[0] ? language[0] : '-', language[1] ? language[1] : '-',
                 country[0] ? country[0] : '-', country[1] ? country[1] : '-',
                 orientation, touchscreen, density, keyboard, navigation, inputFlags,
-                screenWidth, screenHeight, screenWidthDp, screenHeightDp,
+                screenWidth, screenHeight, smallestScreenWidthDp, screenWidthDp, screenHeightDp,
                 screenLayout&MASK_SCREENSIZE, screenLayout&MASK_SCREENLONG,
                 uiMode&MASK_UI_MODE_TYPE, uiMode&MASK_UI_MODE_NIGHT,
                 sdkVersion, minorVersion);
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index aa9b40e..1ca0a19 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -35,6 +35,9 @@
 #define DEFAULT_TEXT_CACHE_WIDTH 1024
 #define DEFAULT_TEXT_CACHE_HEIGHT 256
 
+#define MAX_TEXT_CACHE_WIDTH 2048
+#define MAX_TEXT_CACHE_HEIGHT 2048
+
 ///////////////////////////////////////////////////////////////////////////////
 // Font
 ///////////////////////////////////////////////////////////////////////////////
@@ -386,9 +389,17 @@
 bool FontRenderer::cacheBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) {
     // If the glyph is too tall, don't cache it
     if (glyph.fHeight > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
-        LOGE("Font size to large to fit in cache. width, height = %i, %i",
-                (int) glyph.fWidth, (int) glyph.fHeight);
-        return false;
+        if (mCacheHeight < MAX_TEXT_CACHE_HEIGHT) {
+            // Default cache not large enough for large glyphs - resize cache to
+            // max size and try again
+            flushAllAndInvalidate();
+            initTextTexture(true);
+        }
+        if (glyph.fHeight > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+            LOGE("Font size to large to fit in cache. width, height = %i, %i",
+                    (int) glyph.fWidth, (int) glyph.fHeight);
+            return false;
+        }
     }
 
     // Now copy the bitmap into the cache texture
@@ -446,16 +457,25 @@
     return true;
 }
 
-void FontRenderer::initTextTexture() {
+void FontRenderer::initTextTexture(bool largeFonts) {
+    mCacheLines.clear();
+    if (largeFonts) {
+        mCacheWidth = MAX_TEXT_CACHE_WIDTH;
+        mCacheHeight = MAX_TEXT_CACHE_HEIGHT;
+    }
+
     mTextTexture = new uint8_t[mCacheWidth * mCacheHeight];
     memset(mTextTexture, 0, mCacheWidth * mCacheHeight * sizeof(uint8_t));
 
     mUploadTexture = false;
 
+    if (mTextureId != 0) {
+        glDeleteTextures(1, &mTextureId);
+    }
     glGenTextures(1, &mTextureId);
     glBindTexture(GL_TEXTURE_2D, mTextureId);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    // Initialize texture dimentions
+    // Initialize texture dimensions
     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mCacheWidth, mCacheHeight, 0,
             GL_ALPHA, GL_UNSIGNED_BYTE, 0);
 
@@ -480,6 +500,15 @@
     nextLine += mCacheLines.top()->mMaxHeight;
     mCacheLines.push(new CacheTextureLine(mCacheWidth, 42, nextLine, 0));
     nextLine += mCacheLines.top()->mMaxHeight;
+    if (largeFonts) {
+        int nextSize = 76;
+        // Make several new lines with increasing font sizes
+        while (nextSize < (int)(mCacheHeight - nextLine - (2 * nextSize))) {
+            mCacheLines.push(new CacheTextureLine(mCacheWidth, nextSize, nextLine, 0));
+            nextLine += mCacheLines.top()->mMaxHeight;
+            nextSize += 50;
+        }
+    }
     mCacheLines.push(new CacheTextureLine(mCacheWidth, mCacheHeight - nextLine, nextLine, 0));
 }
 
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index f685d5f..95f714f 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -229,7 +229,7 @@
         }
     };
 
-    void initTextTexture();
+    void initTextTexture(bool largeFonts = false);
     bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
 
     void flushAllAndInvalidate();
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index f4e3f57..3f2d67a 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -49,6 +49,12 @@
 void rsaElementGetNativeData(RsContext, RsElement, uint32_t *elemData, uint32_t elemDataSize);
 void rsaElementGetSubElements(RsContext, RsElement, uint32_t *ids, const char **names, uint32_t dataSize);
 
+RsDevice rsDeviceCreate();
+void rsDeviceDestroy(RsDevice dev);
+void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value);
+RsContext rsContextCreate(RsDevice dev, uint32_t version);
+RsContext rsContextCreateGL(RsDevice dev, uint32_t version, RsSurfaceConfig sc, uint32_t dpi);
+
 
 
 #ifdef ANDROID_RS_SERIALIZE
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 4c8b5db..87d764d 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -1,42 +1,4 @@
 
-DeviceCreate {
-    direct
-    nocontext
-    ret RsDevice
-}
-
-DeviceDestroy {
-    direct
-    nocontext
-    param RsDevice dev
-}
-
-DeviceSetConfig {
-    direct
-    nocontext
-    param RsDevice dev
-    param RsDeviceParam p
-    param int32_t value
-}
-
-ContextCreate {
-    direct
-    nocontext
-    param RsDevice dev
-    param uint32_t version
-    ret RsContext
-}
-
-ContextCreateGL {
-    direct
-    nocontext
-    param RsDevice dev
-    param uint32_t version
-    param RsSurfaceConfig sc
-    param uint32_t dpi
-    ret RsContext
-}
-
 ContextDestroy {
     direct
 }
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index d3bd0d9..bab5c58 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -637,22 +637,6 @@
     LOGV("rsContextDestroy 2 %p", rsc);
 }
 
-RsContext rsi_ContextCreate(RsDevice vdev, uint32_t version) {
-    LOGV("rsContextCreate %p", vdev);
-    Device * dev = static_cast<Device *>(vdev);
-    Context *rsc = Context::createContext(dev, NULL);
-    return rsc;
-}
-
-RsContext rsi_ContextCreateGL(RsDevice vdev, uint32_t version,
-                            RsSurfaceConfig sc, uint32_t dpi) {
-    LOGV("rsContextCreateGL %p", vdev);
-    Device * dev = static_cast<Device *>(vdev);
-    Context *rsc = Context::createContext(dev, &sc);
-    rsc->setDPI(dpi);
-    LOGV("rsContextCreateGL ret %p ", rsc);
-    return rsc;
-}
 
 RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
                                            size_t * receiveLen, size_t receiveLen_length,
@@ -679,6 +663,23 @@
 }
 }
 
+RsContext rsContextCreate(RsDevice vdev, uint32_t version) {
+    LOGV("rsContextCreate %p", vdev);
+    Device * dev = static_cast<Device *>(vdev);
+    Context *rsc = Context::createContext(dev, NULL);
+    return rsc;
+}
+
+RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
+                            RsSurfaceConfig sc, uint32_t dpi) {
+    LOGV("rsContextCreateGL %p", vdev);
+    Device * dev = static_cast<Device *>(vdev);
+    Context *rsc = Context::createContext(dev, &sc);
+    rsc->setDPI(dpi);
+    LOGV("rsContextCreateGL ret %p ", rsc);
+    return rsc;
+}
+
 // Only to be called at a3d load time, before object is visible to user
 // not thread safe
 void rsaGetName(RsContext con, void * obj, const char **name) {
diff --git a/libs/rs/rsDevice.cpp b/libs/rs/rsDevice.cpp
index 849fd98..d7d03f6 100644
--- a/libs/rs/rsDevice.cpp
+++ b/libs/rs/rsDevice.cpp
@@ -40,20 +40,17 @@
     }
 }
 
-namespace android {
-namespace renderscript {
-
-RsDevice rsi_DeviceCreate() {
+RsDevice rsDeviceCreate() {
     Device * d = new Device();
     return d;
 }
 
-void rsi_DeviceDestroy(RsDevice dev) {
+void rsDeviceDestroy(RsDevice dev) {
     Device * d = static_cast<Device *>(dev);
     delete d;
 }
 
-void rsi_DeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) {
+void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) {
     Device * d = static_cast<Device *>(dev);
     if (p == RS_DEVICE_PARAM_FORCE_SOFTWARE_GL) {
         d->mForceSW = value != 0;
@@ -62,5 +59,3 @@
     rsAssert(0);
 }
 
-}
-}
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 2034486..9f55a71 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -345,6 +345,10 @@
     const_cast<RefBase*>(this)->onFirstRef();
 }
 
+void RefBase::destroy() const {
+    delete this;
+}
+
 void RefBase::decStrong(const void* id) const
 {
     weakref_impl* const refs = mRefs;
@@ -357,7 +361,7 @@
     if (c == 1) {
         const_cast<RefBase*>(this)->onLastStrongRef(id);
         if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
-            delete this;
+            destroy();
         }
     }
     refs->decWeak(id);
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 784c9d2..4a6a3db 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -2588,7 +2588,7 @@
 {
     mLock.lock();
     TABLE_GETENTRY(LOGI("Setting parameters: imsi:%d/%d lang:%c%c cnt:%c%c "
-                        "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d %ddp x %ddp\n",
+                        "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d sw%ddp w%ddp h%ddp\n",
                        params->mcc, params->mnc,
                        params->language[0] ? params->language[0] : '-',
                        params->language[1] ? params->language[1] : '-',
@@ -2602,6 +2602,7 @@
                        params->navigation,
                        params->screenWidth,
                        params->screenHeight,
+                       params->smallestScreenWidthDp,
                        params->screenWidthDp,
                        params->screenHeightDp));
     mParams = *params;
@@ -3927,7 +3928,7 @@
         TABLE_GETENTRY(LOGI("Match entry 0x%x in type 0x%x (sz 0x%x): imsi:%d/%d=%d/%d "
                             "lang:%c%c=%c%c cnt:%c%c=%c%c orien:%d=%d touch:%d=%d "
                             "density:%d=%d key:%d=%d inp:%d=%d nav:%d=%d w:%d=%d h:%d=%d "
-                            "wdp:%d=%d hdp:%d=%d\n",
+                            "swdp:%d=%d wdp:%d=%d hdp:%d=%d\n",
                            entryIndex, typeIndex+1, dtohl(thisType->config.size),
                            thisConfig.mcc, thisConfig.mnc,
                            config ? config->mcc : 0, config ? config->mnc : 0,
@@ -3955,6 +3956,8 @@
                            config ? config->screenWidth : 0,
                            thisConfig.screenHeight,
                            config ? config->screenHeight : 0,
+                           thisConfig.smallestScreenWidthDp,
+                           config ? config->smallestScreenWidthDp : 0,
                            thisConfig.screenWidthDp,
                            config ? config->screenWidthDp : 0,
                            thisConfig.screenHeightDp,
@@ -4244,7 +4247,7 @@
                 thisConfig.copyFromDtoH(type->config);
                 LOGI("Adding config to type %d: imsi:%d/%d lang:%c%c cnt:%c%c "
                      "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d "
-                     "wdp:%d hdp:%d\n",
+                     "swdp:%d wdp:%d hdp:%d\n",
                       type->id,
                       thisConfig.mcc, thisConfig.mnc,
                       thisConfig.language[0] ? thisConfig.language[0] : '-',
@@ -4259,6 +4262,7 @@
                       thisConfig.navigation,
                       thisConfig.screenWidth,
                       thisConfig.screenHeight,
+                      thisConfig.smallestScreenWidthDp,
                       thisConfig.screenWidthDp,
                       thisConfig.screenHeightDp));
             t->configs.add(type);
@@ -4753,6 +4757,9 @@
                     if (type->config.screenHeight != 0) {
                         printf(" h=%d", dtohs(type->config.screenHeight));
                     }
+                    if (type->config.smallestScreenWidthDp != 0) {
+                        printf(" swdp=%d", dtohs(type->config.smallestScreenWidthDp));
+                    }
                     if (type->config.screenWidthDp != 0) {
                         printf(" wdp=%d", dtohs(type->config.screenWidthDp));
                     }
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 352579a..a54cf28 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -176,6 +176,7 @@
         addFileType("OGG", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG);
         addFileType("OGA", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG);
         addFileType("AAC", FILE_TYPE_AAC, "audio/aac", MtpConstants.FORMAT_AAC);
+        addFileType("AAC", FILE_TYPE_AAC, "audio/aac-adts", MtpConstants.FORMAT_AAC);
         addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska");
  
         addFileType("MID", FILE_TYPE_MID, "audio/midi");
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 0f5a440..38202f2 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -347,7 +347,7 @@
     }
 
     /**
-     * Store the geodata (latitude and longitude) in the output file.
+     * Set and store the geodata (latitude and longitude) in the output file.
      * This method should be called before prepare(). The geodata is
      * stored in udta box if the output format is OutputFormat.THREE_GPP
      * or OutputFormat.MPEG_4, and is ignored for other output formats.
@@ -361,18 +361,17 @@
      * @throws IllegalArgumentException if the given latitude or
      * longitude is out of range.
      *
-     * {@hide}
      */
-    public void setGeoData(float latitude, float longitude) {
+    public void setLocation(float latitude, float longitude) {
         int latitudex10000  = (int) (latitude * 10000 + 0.5);
         int longitudex10000 = (int) (longitude * 10000 + 0.5);
 
         if (latitudex10000 > 900000 || latitudex10000 < -900000) {
-            String msg = "Unsupported latitude: " + latitude;
+            String msg = "Latitude: " + latitude + " out of range.";
             throw new IllegalArgumentException(msg);
         }
         if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
-            String msg = "Unsupported longitude: " + longitude;
+            String msg = "Longitude: " + longitude + " out of range";
             throw new IllegalArgumentException(msg);
         }
 
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index af2f6ac..3e4e493 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -24,6 +24,7 @@
 
 #include "android/net/android_network_library_impl.h"
 #include "base/thread.h"
+#include "net/base/cert_verifier.h"
 #include "net/base/host_resolver.h"
 #include "net/base/ssl_config_service.h"
 #include "net/http/http_auth_handler_factory.h"
@@ -127,6 +128,7 @@
 
     http_transaction_factory_ = new net::HttpCache(
             host_resolver_,
+            new net::CertVerifier(),
             dnsrr_resolver_,
             dns_cert_checker_.get(),
             proxy_service_.get(),
@@ -174,44 +176,44 @@
 }
 
 void SfDelegate::OnReceivedRedirect(
-            URLRequest *request, const GURL &new_url, bool *defer_redirect) {
+            net::URLRequest *request, const GURL &new_url, bool *defer_redirect) {
     MY_LOGI("OnReceivedRedirect");
 }
 
 void SfDelegate::OnAuthRequired(
-            URLRequest *request, net::AuthChallengeInfo *auth_info) {
+            net::URLRequest *request, net::AuthChallengeInfo *auth_info) {
     MY_LOGI("OnAuthRequired");
 
     inherited::OnAuthRequired(request, auth_info);
 }
 
 void SfDelegate::OnCertificateRequested(
-            URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
+            net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
     MY_LOGI("OnCertificateRequested");
 
     inherited::OnCertificateRequested(request, cert_request_info);
 }
 
 void SfDelegate::OnSSLCertificateError(
-            URLRequest *request, int cert_error, net::X509Certificate *cert) {
+            net::URLRequest *request, int cert_error, net::X509Certificate *cert) {
     fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
 
     inherited::OnSSLCertificateError(request, cert_error, cert);
 }
 
-void SfDelegate::OnGetCookies(URLRequest *request, bool blocked_by_policy) {
+void SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) {
     MY_LOGI("OnGetCookies");
 }
 
 void SfDelegate::OnSetCookie(
-        URLRequest *request,
+        net::URLRequest *request,
         const std::string &cookie_line,
         const net::CookieOptions &options,
         bool blocked_by_policy) {
     MY_LOGI("OnSetCookie");
 }
 
-void SfDelegate::OnResponseStarted(URLRequest *request) {
+void SfDelegate::OnResponseStarted(net::URLRequest *request) {
     if (request->status().status() != URLRequestStatus::SUCCESS) {
         MY_LOGI(StringPrintf(
                     "Request failed with status %d and os_error %d",
@@ -260,7 +262,7 @@
             request->GetExpectedContentSize(), contentType.c_str());
 }
 
-void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) {
+void SfDelegate::OnReadCompleted(net::URLRequest *request, int bytes_read) {
     if (bytes_read == -1) {
         MY_LOGI(StringPrintf(
                     "OnReadCompleted, read failed, status %d",
@@ -297,7 +299,7 @@
     readMore(request);
 }
 
-void SfDelegate::readMore(URLRequest *request) {
+void SfDelegate::readMore(net::URLRequest *request) {
     while (mNumBytesRead < mNumBytesTotal) {
         size_t copy = mNumBytesTotal - mNumBytesRead;
         if (copy > mReadBuffer->size()) {
@@ -371,7 +373,7 @@
         off64_t offset) {
     CHECK(mURLRequest == NULL);
 
-    mURLRequest = new URLRequest(url, this);
+    mURLRequest = new net::URLRequest(url, this);
     mAtEOS = false;
 
     mRangeRequested = false;
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
index 634ac93..4d03493 100644
--- a/media/libstagefright/chromium_http/support.h
+++ b/media/libstagefright/chromium_http/support.h
@@ -77,7 +77,7 @@
 
 struct ChromiumHTTPDataSource;
 
-struct SfDelegate : public URLRequest::Delegate {
+struct SfDelegate : public net::URLRequest::Delegate {
     SfDelegate();
     virtual ~SfDelegate();
 
@@ -92,35 +92,35 @@
     void setOwner(ChromiumHTTPDataSource *mOwner);
 
     virtual void OnReceivedRedirect(
-            URLRequest *request, const GURL &new_url, bool *defer_redirect);
+            net::URLRequest *request, const GURL &new_url, bool *defer_redirect);
 
     virtual void OnAuthRequired(
-            URLRequest *request, net::AuthChallengeInfo *auth_info);
+            net::URLRequest *request, net::AuthChallengeInfo *auth_info);
 
     virtual void OnCertificateRequested(
-            URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
+            net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
 
     virtual void OnSSLCertificateError(
-            URLRequest *request, int cert_error, net::X509Certificate *cert);
+            net::URLRequest *request, int cert_error, net::X509Certificate *cert);
 
-    virtual void OnGetCookies(URLRequest *request, bool blocked_by_policy);
+    virtual void OnGetCookies(net::URLRequest *request, bool blocked_by_policy);
 
     virtual void OnSetCookie(
-            URLRequest *request,
+            net::URLRequest *request,
             const std::string &cookie_line,
             const net::CookieOptions &options,
             bool blocked_by_policy);
 
-    virtual void OnResponseStarted(URLRequest *request);
+    virtual void OnResponseStarted(net::URLRequest *request);
 
-    virtual void OnReadCompleted(URLRequest *request, int bytes_read);
+    virtual void OnReadCompleted(net::URLRequest *request, int bytes_read);
 
 private:
     typedef Delegate inherited;
 
     ChromiumHTTPDataSource *mOwner;
 
-    URLRequest *mURLRequest;
+    net::URLRequest *mURLRequest;
     scoped_refptr<net::IOBufferWithSize> mReadBuffer;
 
     size_t mNumBytesRead;
@@ -130,7 +130,7 @@
     bool mRangeRequested;
     bool mAtEOS;
 
-    void readMore(URLRequest *request);
+    void readMore(net::URLRequest *request);
 
     static void OnInitiateConnectionWrapper(
             SfDelegate *me,
diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp
index d76164f..687924b 100644
--- a/native/android/configuration.cpp
+++ b/native/android/configuration.cpp
@@ -111,6 +111,18 @@
 
 }
 
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) {
+    return config->screenWidthDp;
+}
+
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) {
+    return config->screenHeightDp;
+}
+
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) {
+    return config->smallestScreenWidthDp;
+}
+
 // ----------------------------------------------------------------------
 
 void AConfiguration_setMcc(AConfiguration* config, int32_t mcc) {
@@ -186,6 +198,18 @@
 
 }
 
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) {
+    config->screenWidthDp = value;
+}
+
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) {
+    config->screenHeightDp = value;
+}
+
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) {
+    config->smallestScreenWidthDp = value;
+}
+
 // ----------------------------------------------------------------------
 
 int32_t AConfiguration_diff(AConfiguration* config1, AConfiguration* config2) {
diff --git a/native/include/android/configuration.h b/native/include/android/configuration.h
index 99e8f97..91533c8 100644
--- a/native/include/android/configuration.h
+++ b/native/include/android/configuration.h
@@ -82,6 +82,12 @@
     ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1,
     ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2,
 
+    ACONFIGURATION_SCREEN_WIDTH_DP_ANY = 0x0000,
+
+    ACONFIGURATION_SCREEN_HEIGHT_DP_ANY = 0x0000,
+
+    ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000,
+
     ACONFIGURATION_MCC = 0x0001,
     ACONFIGURATION_MNC = 0x0002,
     ACONFIGURATION_LOCALE = 0x0004,
@@ -95,6 +101,7 @@
     ACONFIGURATION_VERSION = 0x0400,
     ACONFIGURATION_SCREEN_LAYOUT = 0x0800,
     ACONFIGURATION_UI_MODE = 0x1000,
+    ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000,
 };
 
 /**
@@ -286,6 +293,39 @@
 void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
 
 /**
+ * Return the current configuration screen width in dp units, or
+ * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
+ */
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+
+/**
+ * Set the configuration's current screen width in dp units.
+ */
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+
+/**
+ * Return the current configuration screen height in dp units, or
+ * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
+ */
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+
+/**
+ * Set the configuration's current screen width in dp units.
+ */
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+
+/**
+ * Return the configuration's smallest screen width in dp units, or
+ * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
+ */
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+
+/**
+ * Set the configuration's smallest screen width in dp units.
+ */
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
+
+/**
  * Perform a diff between two configurations.  Returns a bit mask of
  * ACONFIGURATION_* constants, each bit set meaning that configuration element
  * is different between them.
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 0747efb..afefee6 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -7,7 +7,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= 	       \
+	EGL/egl_tls.cpp        \
+	EGL/egl_display.cpp    \
+	EGL/egl_object.cpp     \
 	EGL/egl.cpp 	       \
+	EGL/eglApi.cpp 	       \
 	EGL/trace.cpp              \
 	EGL/getProcAddress.cpp.arm \
 	EGL/hooks.cpp 	       \
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index aabba28..31fe306 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -17,14 +17,9 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
 
-#include <sys/ioctl.h>
-
-#ifdef HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
+#include <hardware/gralloc.h>
+#include <system/window.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -36,266 +31,41 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
 #include <utils/String8.h>
 
-#include <ui/egl/android_natives.h>
-
-#include "hooks.h"
 #include "egl_impl.h"
-#include "Loader.h"
-#include "glesv2dbg.h"
 #include "egl_tls.h"
+#include "glesv2dbg.h"
+#include "hooks.h"
+#include "Loader.h"
 
-#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
+#include "egl_display.h"
+#include "egl_object.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-#define VERSION_MAJOR 1
-#define VERSION_MINOR 4
-static char const * const gVendorString     = "Android";
-static char const * const gVersionString    = "1.4 Android META-EGL";
-static char const * const gClientApiString  = "OpenGL ES";
-static char const * const gExtensionString  =
-        "EGL_KHR_image "
-        "EGL_KHR_image_base "
-        "EGL_KHR_image_pixmap "
-        "EGL_KHR_gl_texture_2D_image "
-        "EGL_KHR_gl_texture_cubemap_image "
-        "EGL_KHR_gl_renderbuffer_image "
-        "EGL_KHR_fence_sync "
-        "EGL_ANDROID_image_native_buffer "
-        "EGL_ANDROID_swap_rectangle "
-        ;
+egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
+gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+gl_hooks_t gHooksNoContext;
+pthread_key_t gGLWrapperKey = -1;
 
 // ----------------------------------------------------------------------------
 
-class egl_object_t;
-struct egl_display_t;
-static egl_display_t* get_display(EGLDisplay dpy);
-
-struct egl_config_t {
-    egl_config_t() {}
-    egl_config_t(int impl, EGLConfig config)
-        : impl(impl), config(config), configId(0), implConfigId(0) { }
-    int         impl;           // the implementation this config is for
-    EGLConfig   config;         // the implementation's EGLConfig
-    EGLint      configId;       // our CONFIG_ID
-    EGLint      implConfigId;   // the implementation's CONFIG_ID
-    inline bool operator < (const egl_config_t& rhs) const {
-        if (impl < rhs.impl) return true;
-        if (impl > rhs.impl) return false;
-        return config < rhs.config;
-    }
-};
-
-struct egl_display_t {
-    enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
-
-    struct strings_t {
-        char const * vendor;
-        char const * version;
-        char const * clientApi;
-        char const * extensions;
-    };
-
-    struct DisplayImpl {
-        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
-                        state(NOT_INITIALIZED), numConfigs(0) { }
-        EGLDisplay  dpy;
-        EGLConfig*  config;
-        EGLint      state;
-        EGLint      numConfigs;
-        strings_t   queryString;
-    };
-
-    uint32_t        magic;
-    DisplayImpl     disp[IMPL_NUM_IMPLEMENTATIONS];
-    EGLint          numTotalConfigs;
-    egl_config_t*   configs;
-    uint32_t        refs;
-    Mutex           lock;
-
-    SortedVector<egl_object_t*> objects;
-
-    egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) { }
-    ~egl_display_t() { magic = 0; }
-    inline bool isReady() const { return (refs > 0); }
-    inline bool isValid() const { return magic == '_dpy'; }
-    inline bool isAlive() const { return isValid(); }
-};
-
-class egl_object_t {
-    egl_display_t *display;
-            volatile int32_t  terminated;
-    mutable volatile int32_t  count;
-
-public:
-    egl_object_t(EGLDisplay dpy) : display(get_display(dpy)), terminated(0), count(1) {
-        Mutex::Autolock _l(display->lock);
-        display->objects.add(this);
-    }
-
-    inline bool isAlive() const { return !terminated; }
-
-private:
-    bool get() {
-        Mutex::Autolock _l(display->lock);
-        if (display->objects.indexOf(this) >= 0) {
-            android_atomic_inc(&count);
-            return true;
-        }
-        return false;
-    }
-
-    bool put() {
-        Mutex::Autolock _l(display->lock);
-        if (android_atomic_dec(&count) == 1) {
-            display->objects.remove(this);
-            return true;
-        }
-        return false;
-    }    
-
-public:
-    template <typename N, typename T>
-    struct LocalRef {
-        N* ref;
-        LocalRef(T o) : ref(0) {
-            N* native = reinterpret_cast<N*>(o);
-            if (o && native->get()) {
-                ref = native;
-            }
-        }
-        ~LocalRef() { 
-            if (ref && ref->put()) {
-                delete ref;
-            }
-        }
-        inline N* get() {
-            return ref;
-        }
-        void acquire() const {
-            if (ref) {
-                android_atomic_inc(&ref->count);
-            }
-        }
-        void release() const {
-            if (ref) {
-                int32_t c = android_atomic_dec(&ref->count);
-                // ref->count cannot be 1 prior atomic_dec because we have
-                // a reference, and if we have one, it means there was
-                // already one before us.
-                LOGE_IF(c==1, "refcount is now 0 in release()");
-            }
-        }
-        void terminate() {
-            if (ref) {
-                ref->terminated = 1;
-                release();
-            }
-        }
-    };
-};
-
-struct egl_surface_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
-
-    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
-            EGLSurface surface, int impl, egl_connection_t const* cnx)
-      : egl_object_t(dpy), dpy(dpy), surface(surface), config(config), win(win), impl(impl), cnx(cnx) {
-    }
-    ~egl_surface_t() {
-    }
-    EGLDisplay                  dpy;
-    EGLSurface                  surface;
-    EGLConfig                   config;
-    sp<ANativeWindow>           win;
-    int                         impl;
-    egl_connection_t const*     cnx;
-};
-
-struct egl_context_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
-
-    egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
-            int impl, egl_connection_t const* cnx, int version)
-    : egl_object_t(dpy), dpy(dpy), context(context), config(config), read(0), draw(0),
-      impl(impl), cnx(cnx), version(version)
-    {
-    }
-    ~egl_context_t()
-    {
-    }
-    EGLDisplay                  dpy;
-    EGLContext                  context;
-    EGLConfig                   config;
-    EGLSurface                  read;
-    EGLSurface                  draw;
-    int                         impl;
-    egl_connection_t const*     cnx;
-    int                         version;
-};
-
-struct egl_image_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
-
-    egl_image_t(EGLDisplay dpy, EGLContext context)
-        : egl_object_t(dpy), dpy(dpy), context(context)
-    {
-        memset(images, 0, sizeof(images));
-    }
-    EGLDisplay dpy;
-    EGLContext context;
-    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
-};
-
-struct egl_sync_t : public egl_object_t
-{
-    typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
-
-    egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync)
-        : egl_object_t(dpy), dpy(dpy), context(context), sync(sync)
-    {
-    }
-    EGLDisplay dpy;
-    EGLContext context;
-    EGLSyncKHR sync;
-};
-
-typedef egl_surface_t::Ref  SurfaceRef;
-typedef egl_context_t::Ref  ContextRef;
-typedef egl_image_t::Ref    ImageRef;
-typedef egl_sync_t::Ref     SyncRef;
-
-// ----------------------------------------------------------------------------
-
-static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
-static egl_display_t gDisplay[NUM_DISPLAYS];
-static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t gEGLThreadLocalStorageKey = -1;
-
-// ----------------------------------------------------------------------------
-
-EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
-EGLAPI gl_hooks_t gHooksNoContext;
-EGLAPI pthread_key_t gGLWrapperKey = -1;
-
 #if EGL_TRACE
 
 EGLAPI pthread_key_t gGLTraceKey = -1;
 
 // ----------------------------------------------------------------------------
 
-static int gEGLTraceLevel, gEGLDebugLevel;
-static int gEGLApplicationTraceLevel;
-extern EGLAPI gl_hooks_t gHooksTrace, gHooksDebug;
+int gEGLDebugLevel;
+
+static int sEGLTraceLevel;
+static int sEGLApplicationTraceLevel;
+
+extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksDebug;
 
 static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
     pthread_setspecific(gGLTraceKey, value);
@@ -305,12 +75,12 @@
     return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
 }
 
-static void initEglTraceLevel() {
+void initEglTraceLevel() {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.egl.trace", value, "0");
     int propertyLevel = atoi(value);
-    int applicationLevel = gEGLApplicationTraceLevel;
-    gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
+    int applicationLevel = sEGLApplicationTraceLevel;
+    sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
 
     property_get("debug.egl.debug_proc", value, "");
     long pid = getpid();
@@ -323,12 +93,12 @@
         if (fgets(cmdline, sizeof(cmdline) - 1, file))
         {
             if (!strcmp(value, cmdline))
-                gEGLDebugLevel = 1;
+                sEGLTraceLevel = 1;
         }
         fclose(file);
     }
 
-    if (gEGLDebugLevel > 0)
+    if (sEGLTraceLevel > 0)
     {
         property_get("debug.egl.debug_port", value, "5039");
         const unsigned short port = (unsigned short)atoi(value);
@@ -341,11 +111,11 @@
     }
 }
 
-static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
-    if (gEGLTraceLevel > 0) {
+void setGLHooksThreadSpecific(gl_hooks_t const *value) {
+    if (sEGLTraceLevel > 0) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksTrace);
-    } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
+    } else if (sEGLTraceLevel > 0 && value != &gHooksNoContext) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksDebug);
     } else {
@@ -359,186 +129,21 @@
  */
 extern "C"
 void setGLTraceLevel(int level) {
-    gEGLApplicationTraceLevel = level;
+    sEGLApplicationTraceLevel = level;
 }
 
 #else
 
-static inline void setGLHooksThreadSpecific(gl_hooks_t const *value) {
+void setGLHooksThreadSpecific(gl_hooks_t const *value) {
     setGlThreadSpecific(value);
 }
 
 #endif
 
-// ----------------------------------------------------------------------------
-
-static __attribute__((noinline))
-const char *egl_strerror(EGLint err)
-{
-    switch (err){
-        case EGL_SUCCESS:               return "EGL_SUCCESS";
-        case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
-        case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
-        case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
-        case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
-        case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
-        case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
-        case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
-        case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
-        case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
-        case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
-        case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
-        case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
-        case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
-        case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
-        default: return "UNKNOWN";
-    }
-}
-
-static __attribute__((noinline))
-void clearTLS() {
-    if (gEGLThreadLocalStorageKey != -1) {
-        tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-        if (tls) {
-            delete tls;
-            pthread_setspecific(gEGLThreadLocalStorageKey, 0);
-        }
-    }
-}
-
-static tls_t* getTLS()
-{
-    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-    if (tls == 0) {
-        tls = new tls_t;
-        pthread_setspecific(gEGLThreadLocalStorageKey, tls);
-    }
-    return tls;
-}
-
-static inline void clearError() {
-    // This must clear the error from all the underlying EGL implementations as
-    // well as the EGL wrapper layer.
-    eglGetError();
-}
-
-template<typename T>
-static __attribute__((noinline))
-T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) {
-    if (gEGLThreadLocalStorageKey == -1) {
-        pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
-        if (gEGLThreadLocalStorageKey == -1)
-            pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
-        pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
-    }
-    tls_t* tls = getTLS();
-    if (tls->error != error) {
-        LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
-        tls->error = error;
-    }
-    return returnValue;
-}
-
-static __attribute__((noinline))
-GLint getError() {
-    if (gEGLThreadLocalStorageKey == -1)
-        return EGL_SUCCESS;
-    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-    if (!tls) return EGL_SUCCESS;
-    GLint error = tls->error;
-    tls->error = EGL_SUCCESS;
-    return error;
-}
-
-static __attribute__((noinline))
-void setContext(EGLContext ctx) {
-    if (gEGLThreadLocalStorageKey == -1) {
-        pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
-        if (gEGLThreadLocalStorageKey == -1)
-            pthread_key_create(&gEGLThreadLocalStorageKey, NULL);
-        pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
-    }
-    tls_t* tls = getTLS();
-    tls->ctx = ctx;
-}
-
-static __attribute__((noinline))
-EGLContext getContext() {
-    if (gEGLThreadLocalStorageKey == -1)
-        return EGL_NO_CONTEXT;
-    tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey);
-    if (!tls) return EGL_NO_CONTEXT;
-    return tls->ctx;
-}
-
 /*****************************************************************************/
 
-template<typename T>
-static __attribute__((noinline))
-int binarySearch(
-        T const sortedArray[], int first, int last, T key)
-{
-    while (first <= last) {
-        int mid = (first + last) / 2;
-        if (sortedArray[mid] < key) {
-            first = mid + 1;
-        } else if (key < sortedArray[mid]) { 
-            last = mid - 1;
-        } else {
-            return mid;
-        }
-    }
-    return -1;
-}
-
-static int cmp_configs(const void* a, const void *b)
-{
-    const egl_config_t& c0 = *(egl_config_t const *)a;
-    const egl_config_t& c1 = *(egl_config_t const *)b;
-    return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
-}
-
-struct extention_map_t {
-    const char* name;
-    __eglMustCastToProperFunctionPointerType address;
-};
-
-static const extention_map_t gExtentionMap[] = {
-    { "eglLockSurfaceKHR",  
-            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 
-    { "eglUnlockSurfaceKHR", 
-            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 
-    { "eglCreateImageKHR",  
-            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 
-    { "eglDestroyImageKHR", 
-            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 
-    { "eglSetSwapRectangleANDROID", 
-            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 
-};
-
-extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
-
-// accesses protected by gInitDriverMutex
-static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap;
-static int gGLExtentionSlot = 0;
-
-static void(*findProcAddress(const char* name,
-        const extention_map_t* map, size_t n))() 
-{
-    for (uint32_t i=0 ; i<n ; i++) {
-        if (!strcmp(name, map[i].name)) {
-            return map[i].address;
-        }
-    }
-    return NULL;
-}
-
-// ----------------------------------------------------------------------------
-
 static int gl_no_context() {
-    tls_t* tls = getTLS();
-    if (tls->logCallWithNoContext == EGL_TRUE) {
-        tls->logCallWithNoContext = EGL_FALSE;
+    if (egl_tls_t::logNoContextCall()) {
         LOGE("call to OpenGL ES API with no current context "
              "(logged once per thread)");
     }
@@ -566,55 +171,23 @@
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
 static int sEarlyInitState = pthread_once(&once_control, &early_egl_init);
 
+// ----------------------------------------------------------------------------
 
-static inline
-egl_display_t* get_display(EGLDisplay dpy)
-{
-    uintptr_t index = uintptr_t(dpy)-1U;
-    return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
-}
-
-template<typename NATIVE, typename EGL>
-static inline NATIVE* egl_to_native_cast(EGL arg) {
-    return reinterpret_cast<NATIVE*>(arg);
-}
-
-static inline
-egl_surface_t* get_surface(EGLSurface surface) {
-    return egl_to_native_cast<egl_surface_t>(surface);
-}
-
-static inline
-egl_context_t* get_context(EGLContext context) {
-    return egl_to_native_cast<egl_context_t>(context);
-}
-
-static inline
-egl_image_t* get_image(EGLImageKHR image) {
-    return egl_to_native_cast<egl_image_t>(image);
-}
-
-static inline
-egl_sync_t* get_sync(EGLSyncKHR sync) {
-    return egl_to_native_cast<egl_sync_t>(sync);
-}
-
-static inline
-egl_display_t* validate_display(EGLDisplay dpy)
-{
+egl_display_t* validate_display(EGLDisplay dpy) {
     egl_display_t * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, (egl_display_t*)NULL);
-    if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (egl_display_t*)NULL);
+    if (!dp)
+        return setError(EGL_BAD_DISPLAY, (egl_display_t*)NULL);
+    if (!dp->isReady())
+        return setError(EGL_NOT_INITIALIZED, (egl_display_t*)NULL);
 
     return dp;
 }
 
-static egl_connection_t* validate_display_config(
-        EGLDisplay dpy, EGLConfig config,
-        egl_display_t const*& dp)
-{
+egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig config,
+        egl_display_t const*& dp) {
     dp = validate_display(dpy);
-    if (!dp) return (egl_connection_t*) NULL;
+    if (!dp)
+        return (egl_connection_t*) NULL;
 
     if (intptr_t(config) >= dp->numTotalConfigs) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
@@ -626,41 +199,26 @@
     return cnx;
 }
 
-static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx)
-{
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-    if (!dp->isAlive())
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_context(ctx)->isAlive())
-        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    return EGL_TRUE;
-}
-
-static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface)
-{
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-    if (!dp->isAlive())
-        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_surface(surface)->isAlive())
-        return setError(EGL_BAD_SURFACE, EGL_FALSE);
-    return EGL_TRUE;
-}
+// ----------------------------------------------------------------------------
 
 EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
 {
     ImageRef _i(image);
-    if (!_i.get()) return EGL_NO_IMAGE_KHR;
-    
-    EGLContext context = getContext();
+    if (!_i.get())
+        return EGL_NO_IMAGE_KHR;
+
+    EGLContext context = egl_tls_t::getContext();
     if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
         return EGL_NO_IMAGE_KHR;
-    
+
     egl_context_t const * const c = get_context(context);
-    if (!c->isAlive())
+    if (c == NULL) // this should never happen
         return EGL_NO_IMAGE_KHR;
 
+    // here we don't validate the context because if it's been marked for
+    // termination, this call should still succeed since it's internal to
+    // EGL.
+
     egl_image_t const * const i = get_image(image);
     return i->images[c->impl];
 }
@@ -671,10 +229,7 @@
 //    d->disp[]
 //    egl_init_drivers_locked()
 //
-static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
-
-EGLBoolean egl_init_drivers_locked()
-{
+static EGLBoolean egl_init_drivers_locked() {
     if (sEarlyInitState) {
         // initialized by static ctor. should be set here.
         return EGL_FALSE;
@@ -682,28 +237,15 @@
 
     // get our driver loader
     Loader& loader(Loader::getInstance());
-    
-    // dynamically load all our EGL implementations for all displays
-    // and retrieve the corresponding EGLDisplay
-    // if that fails, don't use this driver.
-    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+
+    // dynamically load all our EGL implementations
     egl_connection_t* cnx;
-    egl_display_t* d = &gDisplay[0];
 
     cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
         cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
         cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
         cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
-        if (cnx->dso) {
-            EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
-            d->disp[IMPL_SOFTWARE].dpy = dpy; 
-            if (dpy == EGL_NO_DISPLAY) {
-                loader.close(cnx->dso);
-                cnx->dso = NULL;
-            }
-        }
     }
 
     cnx = &gEGLImpl[IMPL_HARDWARE];
@@ -714,15 +256,6 @@
             cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
             cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
             cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
-            if (cnx->dso) {
-                EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
-                d->disp[IMPL_HARDWARE].dpy = dpy; 
-                if (dpy == EGL_NO_DISPLAY) {
-                    loader.close(cnx->dso);
-                    cnx->dso = NULL;
-                }
-            }
         } else {
             LOGD("3D hardware acceleration is disabled");
         }
@@ -735,12 +268,13 @@
     return EGL_TRUE;
 }
 
-EGLBoolean egl_init_drivers()
-{
+static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
+
+EGLBoolean egl_init_drivers() {
     EGLBoolean res;
-    pthread_mutex_lock(&gInitDriverMutex);
+    pthread_mutex_lock(&sInitDriverMutex);
     res = egl_init_drivers_locked();
-    pthread_mutex_unlock(&gInitDriverMutex);
+    pthread_mutex_unlock(&sInitDriverMutex);
     return res;
 }
 
@@ -748,1486 +282,3 @@
 }; // namespace android
 // ----------------------------------------------------------------------------
 
-using namespace android;
-
-EGLDisplay eglGetDisplay(NativeDisplayType display)
-{
-    clearError();
-
-    uint32_t index = uint32_t(display);
-    if (index >= NUM_DISPLAYS) {
-        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
-    }
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
-    }
-    
-    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
-    return dpy;
-}
-
-// ----------------------------------------------------------------------------
-// Initialization
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
-{
-    clearError();
-
-    egl_display_t * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    Mutex::Autolock _l(dp->lock);
-
-    if (dp->refs > 0) {
-        if (major != NULL) *major = VERSION_MAJOR;
-        if (minor != NULL) *minor = VERSION_MINOR;
-        dp->refs++;
-        return EGL_TRUE;
-    }
-
-#if EGL_TRACE
-
-    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
-    // the information from that call may be stale.)
-    initEglTraceLevel();
-
-#endif
-
-    setGLHooksThreadSpecific(&gHooksNoContext);
-
-    // initialize each EGL and
-    // build our own extension string first, based on the extension we know
-    // and the extension supported by our client implementation
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        cnx->major = -1;
-        cnx->minor = -1;
-        if (!cnx->dso) 
-            continue;
-
-#if defined(ADRENO130)
-#warning "Adreno-130 eglInitialize() workaround"
-        /*
-         * The ADRENO 130 driver returns a different EGLDisplay each time
-         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
-         * after eglTerminate() has been called, so that eglInitialize() 
-         * cannot be called again. Therefore, we need to make sure to call
-         * eglGetDisplay() before calling eglInitialize();
-         */
-        if (i == IMPL_HARDWARE) {
-            dp->disp[i].dpy =
-                cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        }
-#endif
-
-
-        EGLDisplay idpy = dp->disp[i].dpy;
-        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
-            //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
-            //        i, idpy, cnx->major, cnx->minor, cnx);
-
-            // display is now initialized
-            dp->disp[i].state = egl_display_t::INITIALIZED;
-
-            // get the query-strings for this display for each implementation
-            dp->disp[i].queryString.vendor =
-                cnx->egl.eglQueryString(idpy, EGL_VENDOR);
-            dp->disp[i].queryString.version =
-                cnx->egl.eglQueryString(idpy, EGL_VERSION);
-            dp->disp[i].queryString.extensions =
-                    cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
-            dp->disp[i].queryString.clientApi =
-                cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
-
-        } else {
-            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
-                    egl_strerror(cnx->egl.eglGetError()));
-        }
-    }
-
-    EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
-            EGLint n;
-            if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
-                dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
-                if (dp->disp[i].config) {
-                    if (cnx->egl.eglGetConfigs(
-                            dp->disp[i].dpy, dp->disp[i].config, n,
-                            &dp->disp[i].numConfigs))
-                    {
-                        dp->numTotalConfigs += n;
-                        res = EGL_TRUE;
-                    }
-                }
-            }
-        }
-    }
-
-    if (res == EGL_TRUE) {
-        dp->configs = new egl_config_t[ dp->numTotalConfigs ];
-        for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-            egl_connection_t* const cnx = &gEGLImpl[i];
-            if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
-                for (int j=0 ; j<dp->disp[i].numConfigs ; j++) {
-                    dp->configs[k].impl = i;
-                    dp->configs[k].config = dp->disp[i].config[j];
-                    dp->configs[k].configId = k + 1; // CONFIG_ID start at 1
-                    // store the implementation's CONFIG_ID
-                    cnx->egl.eglGetConfigAttrib(
-                            dp->disp[i].dpy,
-                            dp->disp[i].config[j],
-                            EGL_CONFIG_ID,
-                            &dp->configs[k].implConfigId);
-                    k++;
-                }
-            }
-        }
-
-        // sort our configurations so we can do binary-searches
-        qsort(  dp->configs,
-                dp->numTotalConfigs,
-                sizeof(egl_config_t), cmp_configs);
-
-        dp->refs++;
-        if (major != NULL) *major = VERSION_MAJOR;
-        if (minor != NULL) *minor = VERSION_MINOR;
-        return EGL_TRUE;
-    }
-    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
-}
-
-EGLBoolean eglTerminate(EGLDisplay dpy)
-{
-    // NOTE: don't unload the drivers b/c some APIs can be called
-    // after eglTerminate() has been called. eglTerminate() only
-    // terminates an EGLDisplay, not a EGL itself.
-
-    clearError();
-
-    egl_display_t* const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    Mutex::Autolock _l(dp->lock);
-
-    if (dp->refs == 0) {
-        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
-    }
-
-    // this is specific to Android, display termination is ref-counted.
-    if (dp->refs > 1) {
-        dp->refs--;
-        return EGL_TRUE;
-    }
-
-    EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
-            if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
-                LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
-                        egl_strerror(cnx->egl.eglGetError()));
-            }
-            // REVISIT: it's unclear what to do if eglTerminate() fails
-            free(dp->disp[i].config);
-
-            dp->disp[i].numConfigs = 0;
-            dp->disp[i].config = 0;
-            dp->disp[i].state = egl_display_t::TERMINATED;
-
-            res = EGL_TRUE;
-        }
-    }
-    
-    // TODO: all egl_object_t should be marked for termination
-    
-    dp->refs--;
-    dp->numTotalConfigs = 0;
-    delete [] dp->configs;
-
-    return res;
-}
-
-// ----------------------------------------------------------------------------
-// configuration
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglGetConfigs(   EGLDisplay dpy,
-                            EGLConfig *configs,
-                            EGLint config_size, EGLint *num_config)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    GLint numConfigs = dp->numTotalConfigs;
-    if (!configs) {
-        *num_config = numConfigs;
-        return EGL_TRUE;
-    }
-
-    GLint n = 0;
-    for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
-        *configs++ = EGLConfig(i);
-        config_size--;
-        n++;
-    }
-    
-    *num_config = n;
-    return EGL_TRUE;
-}
-
-EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
-                            EGLConfig *configs, EGLint config_size,
-                            EGLint *num_config)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    if (num_config==0) {
-        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    }
-
-    EGLint n;
-    EGLBoolean res = EGL_FALSE;
-    *num_config = 0;
-
-    
-    // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 
-    // to do this, we have to go through the attrib_list array once
-    // to figure out both its size and if it contains an EGL_CONFIG_ID
-    // key. If so, the full array is copied and patched.
-    // NOTE: we assume that there can be only one occurrence
-    // of EGL_CONFIG_ID.
-    
-    EGLint patch_index = -1;
-    GLint attr;
-    size_t size = 0;
-    if (attrib_list) {
-        while ((attr=attrib_list[size]) != EGL_NONE) {
-            if (attr == EGL_CONFIG_ID)
-                patch_index = size;
-            size += 2;
-        }
-    }
-    if (patch_index >= 0) {
-        size += 2; // we need copy the sentinel as well
-        EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
-        if (new_list == 0)
-            return setError(EGL_BAD_ALLOC, EGL_FALSE);
-        memcpy(new_list, attrib_list, size*sizeof(EGLint));
-
-        // patch the requested EGL_CONFIG_ID
-        bool found = false;
-        EGLConfig ourConfig(0);
-        EGLint& configId(new_list[patch_index+1]);
-        for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
-            if (dp->configs[i].configId == configId) {
-                ourConfig = EGLConfig(i);
-                configId = dp->configs[i].implConfigId;
-                found = true;
-                break;
-            }
-        }
-
-        egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
-        if (found && cnx->dso) {
-            // and switch to the new list
-            attrib_list = const_cast<const EGLint *>(new_list);
-
-            // At this point, the only configuration that can match is
-            // dp->configs[i][index], however, we don't know if it would be
-            // rejected because of the other attributes, so we do have to call
-            // cnx->egl.eglChooseConfig() -- but we don't have to loop
-            // through all the EGLimpl[].
-            // We also know we can only get a single config back, and we know
-            // which one.
-
-            res = cnx->egl.eglChooseConfig(
-                    dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
-                    attrib_list, configs, config_size, &n);
-            if (res && n>0) {
-                // n has to be 0 or 1, by construction, and we already know
-                // which config it will return (since there can be only one).
-                if (configs) {
-                    configs[0] = ourConfig;
-                }
-                *num_config = 1;
-            }
-        }
-
-        free(const_cast<EGLint *>(attrib_list));
-        return res;
-    }
-
-
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglChooseConfig(
-                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
-                if (configs) {
-                    // now we need to convert these client EGLConfig to our
-                    // internal EGLConfig format.
-                    // This is done in O(n Log(n)) time.
-                    for (int j=0 ; j<n ; j++) {
-                        egl_config_t key(i, configs[j]);
-                        intptr_t index = binarySearch<egl_config_t>(
-                                dp->configs, 0, dp->numTotalConfigs, key);
-                        if (index >= 0) {
-                            configs[j] = EGLConfig(index);
-                        } else {
-                            return setError(EGL_BAD_CONFIG, EGL_FALSE);
-                        }
-                    }
-                    configs += n;
-                    config_size -= n;
-                }
-                *num_config += n;
-                res = EGL_TRUE;
-            }
-        }
-    }
-    return res;
-}
-
-EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
-        EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (!cnx) return EGL_FALSE;
-    
-    if (attribute == EGL_CONFIG_ID) {
-        *value = dp->configs[intptr_t(config)].configId;
-        return EGL_TRUE;
-    }
-    return cnx->egl.eglGetConfigAttrib(
-            dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-            dp->configs[intptr_t(config)].config, attribute, value);
-}
-
-// ----------------------------------------------------------------------------
-// surfaces
-// ----------------------------------------------------------------------------
-
-EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
-                                    NativeWindowType window,
-                                    const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
-        EGLConfig iConfig = dp->configs[intptr_t(config)].config;
-        EGLint format;
-
-        // set the native window's buffers format to match this config
-        if (cnx->egl.eglGetConfigAttrib(iDpy,
-                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
-            if (format != 0) {
-                native_window_set_buffers_geometry(window, 0, 0, format);
-            }
-        }
-
-        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
-                iDpy, iConfig, window, attrib_list);
-        if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
-                    dp->configs[intptr_t(config)].impl, cnx);
-            return s;
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-
-EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
-                                    NativePixmapType pixmap,
-                                    const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config, pixmap, attrib_list);
-        if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
-                    dp->configs[intptr_t(config)].impl, cnx);
-            return s;
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-
-EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
-                                    const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config, attrib_list);
-        if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
-                    dp->configs[intptr_t(config)].impl, cnx);
-            return s;
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-                                    
-EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-
-    egl_surface_t * const s = get_surface(surface);
-    EGLBoolean result = s->cnx->egl.eglDestroySurface(
-            dp->disp[s->impl].dpy, s->surface);
-    if (result == EGL_TRUE) {
-        if (s->win != NULL) {
-            native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
-        }
-        _s.terminate();
-    }
-    return result;
-}
-
-EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
-                            EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(surface);
-
-    EGLBoolean result(EGL_TRUE);
-    if (attribute == EGL_CONFIG_ID) {
-        // We need to remap EGL_CONFIG_IDs
-        *value = dp->configs[intptr_t(s->config)].configId;
-    } else {
-        result = s->cnx->egl.eglQuerySurface(
-                dp->disp[s->impl].dpy, s->surface, attribute, value);
-    }
-
-    return result;
-}
-
-// ----------------------------------------------------------------------------
-// Contexts
-// ----------------------------------------------------------------------------
-
-EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
-                            EGLContext share_list, const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (cnx) {
-        if (share_list != EGL_NO_CONTEXT) {
-            egl_context_t* const c = get_context(share_list);
-            share_list = c->context;
-        }
-        EGLContext context = cnx->egl.eglCreateContext(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config,
-                share_list, attrib_list);
-        if (context != EGL_NO_CONTEXT) {
-            // figure out if it's a GLESv1 or GLESv2
-            int version = 0;
-            if (attrib_list) {
-                while (*attrib_list != EGL_NONE) {
-                    GLint attr = *attrib_list++;
-                    GLint value = *attrib_list++;
-                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
-                        if (value == 1) {
-                            version = GLESv1_INDEX;
-                        } else if (value == 2) {
-                            version = GLESv2_INDEX;
-                        }
-                    }
-                };
-            }
-            egl_context_t* c = new egl_context_t(dpy, context, config,
-                    dp->configs[intptr_t(config)].impl, cnx, version);
-            return c;
-        }
-    }
-    return EGL_NO_CONTEXT;
-}
-
-EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-    egl_context_t * const c = get_context(ctx);
-    EGLBoolean result = c->cnx->egl.eglDestroyContext(
-            dp->disp[c->impl].dpy, c->context);
-    if (result == EGL_TRUE) {
-        _c.terminate();
-    }
-    return result;
-}
-
-static void loseCurrent(egl_context_t * cur_c)
-{
-    if (cur_c) {
-        egl_surface_t * cur_r = get_surface(cur_c->read);
-        egl_surface_t * cur_d = get_surface(cur_c->draw);
-
-        // by construction, these are either 0 or valid (possibly terminated)
-        // it should be impossible for these to be invalid
-        ContextRef _cur_c(cur_c);
-        SurfaceRef _cur_r(cur_r);
-        SurfaceRef _cur_d(cur_d);
-
-        cur_c->read = NULL;
-        cur_c->draw = NULL;
-
-        _cur_c.release();
-        _cur_r.release();
-        _cur_d.release();
-    }
-}
-
-EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
-                            EGLSurface read, EGLContext ctx)
-{
-    clearError();
-
-    egl_display_t const * const dp = get_display(dpy);
-    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    /* If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
-       EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
-       a valid but uninitialized display. */
-    if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
-         (draw != EGL_NO_SURFACE) ) {
-        if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
-    }
-
-    // get a reference to the object passed in
-    ContextRef _c(ctx);
-    SurfaceRef _d(draw);
-    SurfaceRef _r(read);
-
-    // validate the context (if not EGL_NO_CONTEXT)
-    if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
-        // EGL_NO_CONTEXT is valid
-        return EGL_FALSE;
-    }
-
-    // these are the underlying implementation's object
-    EGLContext impl_ctx  = EGL_NO_CONTEXT;
-    EGLSurface impl_draw = EGL_NO_SURFACE;
-    EGLSurface impl_read = EGL_NO_SURFACE;
-
-    // these are our objects structs passed in
-    egl_context_t       * c = NULL;
-    egl_surface_t const * d = NULL;
-    egl_surface_t const * r = NULL;
-
-    // these are the current objects structs
-    egl_context_t * cur_c = get_context(getContext());
-    
-    if (ctx != EGL_NO_CONTEXT) {
-        c = get_context(ctx);
-        impl_ctx = c->context;
-    } else {
-        // no context given, use the implementation of the current context
-        if (cur_c == NULL) {
-            // no current context
-            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
-                // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
-                return setError(EGL_BAD_MATCH, EGL_FALSE);
-            }
-            // not an error, there is just no current context.
-            return EGL_TRUE;
-        }
-    }
-
-    // retrieve the underlying implementation's draw EGLSurface
-    if (draw != EGL_NO_SURFACE) {
-        d = get_surface(draw);
-        // make sure the EGLContext and EGLSurface passed in are for
-        // the same driver
-        if (c && d->impl != c->impl)
-            return setError(EGL_BAD_MATCH, EGL_FALSE);
-        impl_draw = d->surface;
-    }
-
-    // retrieve the underlying implementation's read EGLSurface
-    if (read != EGL_NO_SURFACE) {
-        r = get_surface(read);
-        // make sure the EGLContext and EGLSurface passed in are for
-        // the same driver
-        if (c && r->impl != c->impl)
-            return setError(EGL_BAD_MATCH, EGL_FALSE);
-        impl_read = r->surface;
-    }
-
-    EGLBoolean result;
-
-    if (c) {
-        result = c->cnx->egl.eglMakeCurrent(
-                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
-    } else {
-        result = cur_c->cnx->egl.eglMakeCurrent(
-                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
-    }
-
-    if (result == EGL_TRUE) {
-
-        loseCurrent(cur_c);
-
-        if (ctx != EGL_NO_CONTEXT) {
-            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
-            setContext(ctx);
-            tls_t * const tls = getTLS();
-            if (!tls->dbg && gEGLDebugLevel > 0)
-                tls->dbg = CreateDbgContext(gEGLThreadLocalStorageKey, c->version,
-                                            c->cnx->hooks[c->version]);
-            _c.acquire();
-            _r.acquire();
-            _d.acquire();
-            c->read = read;
-            c->draw = draw;
-        } else {
-            setGLHooksThreadSpecific(&gHooksNoContext);
-            setContext(EGL_NO_CONTEXT);
-        }
-    }
-    return result;
-}
-
-
-EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
-                            EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;    
-    
-    egl_context_t * const c = get_context(ctx);
-
-    EGLBoolean result(EGL_TRUE);
-    if (attribute == EGL_CONFIG_ID) {
-        *value = dp->configs[intptr_t(c->config)].configId;
-    } else {
-        // We need to remap EGL_CONFIG_IDs
-        result = c->cnx->egl.eglQueryContext(
-                dp->disp[c->impl].dpy, c->context, attribute, value);
-    }
-
-    return result;
-}
-
-EGLContext eglGetCurrentContext(void)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would correctly return EGL_NO_CONTEXT.
-
-    clearError();
-
-    EGLContext ctx = getContext();
-    return ctx;
-}
-
-EGLSurface eglGetCurrentSurface(EGLint readdraw)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would correctly return EGL_NO_SURFACE.
-
-    clearError();
-
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
-        switch (readdraw) {
-            case EGL_READ: return c->read;
-            case EGL_DRAW: return c->draw;            
-            default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
-        }
-    }
-    return EGL_NO_SURFACE;
-}
-
-EGLDisplay eglGetCurrentDisplay(void)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would correctly return EGL_NO_DISPLAY.
-
-    clearError();
-
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
-        return c->dpy;
-    }
-    return EGL_NO_DISPLAY;
-}
-
-EGLBoolean eglWaitGL(void)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would return GL_TRUE, which isn't wrong.
-
-    clearError();
-
-    EGLBoolean res = EGL_TRUE;
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (uint32_t(c->impl)>=2)
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        egl_connection_t* const cnx = &gEGLImpl[c->impl];
-        if (!cnx->dso) 
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->egl.eglWaitGL();
-    }
-    return res;
-}
-
-EGLBoolean eglWaitNative(EGLint engine)
-{
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would return GL_TRUE, which isn't wrong.
-
-    clearError();
-
-    EGLBoolean res = EGL_TRUE;
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (uint32_t(c->impl)>=2)
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        egl_connection_t* const cnx = &gEGLImpl[c->impl];
-        if (!cnx->dso) 
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->egl.eglWaitNative(engine);
-    }
-    return res;
-}
-
-EGLint eglGetError(void)
-{
-    EGLint result = EGL_SUCCESS;
-    EGLint err;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        err = EGL_SUCCESS;
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso)
-            err = cnx->egl.eglGetError();
-        if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
-            result = err;
-    }
-    err = getError();
-    if (result == EGL_SUCCESS)
-        result = err;
-    return result;
-}
-
-// Note: Similar implementations of these functions also exist in
-// gl2.cpp and gl.cpp, and are used by applications that call the
-// exported entry points directly.
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
-
-static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
-static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
-
-static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
-{
-    GLeglImageOES implImage =
-        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
-    glEGLImageTargetTexture2DOES_impl(target, implImage);
-}
-
-static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
-{
-    GLeglImageOES implImage =
-        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
-    glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
-}
-
-__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
-{
-    // eglGetProcAddress() could be the very first function called
-    // in which case we must make sure we've initialized ourselves, this
-    // happens the first time egl_get_display() is called.
-
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        setError(EGL_BAD_PARAMETER, NULL);
-        return  NULL;
-    }
-
-    __eglMustCastToProperFunctionPointerType addr;
-    addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
-    if (addr) return addr;
-
-    // this protects accesses to gGLExtentionMap and gGLExtentionSlot
-    pthread_mutex_lock(&gInitDriverMutex);
-
-        /*
-         * Since eglGetProcAddress() is not associated to anything, it needs
-         * to return a function pointer that "works" regardless of what
-         * the current context is.
-         *
-         * For this reason, we return a "forwarder", a small stub that takes
-         * care of calling the function associated with the context
-         * currently bound.
-         *
-         * We first look for extensions we've already resolved, if we're seeing
-         * this extension for the first time, we go through all our
-         * implementations and call eglGetProcAddress() and record the
-         * result in the appropriate implementation hooks and return the
-         * address of the forwarder corresponding to that hook set.
-         *
-         */
-
-        const String8 name(procname);
-        addr = gGLExtentionMap.valueFor(name);
-        const int slot = gGLExtentionSlot;
-
-        LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
-                "no more slots for eglGetProcAddress(\"%s\")",
-                procname);
-
-        if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
-            bool found = false;
-            for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-                egl_connection_t* const cnx = &gEGLImpl[i];
-                if (cnx->dso && cnx->egl.eglGetProcAddress) {
-                    found = true;
-                    // Extensions are independent of the bound context
-                    cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
-                    cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
-#if EGL_TRACE
-                    gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
-#endif
-                            cnx->egl.eglGetProcAddress(procname);
-                }
-            }
-            if (found) {
-                addr = gExtensionForwarders[slot];
-
-                if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
-                    glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
-                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
-                }
-                if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
-                    glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
-                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
-                }
-
-                gGLExtentionMap.add(name, addr);
-                gGLExtentionSlot++;
-            }
-        }
-
-    pthread_mutex_unlock(&gInitDriverMutex);
-    return addr;
-}
-
-EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
-{
-    EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
-    if (gEGLDebugLevel > 0)
-        Debug_eglSwapBuffers(dpy, draw);
-
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(draw);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, draw))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(draw);
-    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
-}
-
-EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
-                            NativePixmapType target)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(surface);
-    return s->cnx->egl.eglCopyBuffers(
-            dp->disp[s->impl].dpy, s->surface, target);
-}
-
-const char* eglQueryString(EGLDisplay dpy, EGLint name)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return (const char *) NULL;
-
-    switch (name) {
-        case EGL_VENDOR:
-            return gVendorString;
-        case EGL_VERSION:
-            return gVersionString;
-        case EGL_EXTENSIONS:
-            return gExtensionString;
-        case EGL_CLIENT_APIS:
-            return gClientApiString;
-    }
-    return setError(EGL_BAD_PARAMETER, (const char *)0);
-}
-
-
-// ----------------------------------------------------------------------------
-// EGL 1.1
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglSurfaceAttrib(
-        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->egl.eglSurfaceAttrib) {
-        return s->cnx->egl.eglSurfaceAttrib(
-                dp->disp[s->impl].dpy, s->surface, attribute, value);
-    }
-    return setError(EGL_BAD_SURFACE, EGL_FALSE);
-}
-
-EGLBoolean eglBindTexImage(
-        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->egl.eglBindTexImage) {
-        return s->cnx->egl.eglBindTexImage(
-                dp->disp[s->impl].dpy, s->surface, buffer);
-    }
-    return setError(EGL_BAD_SURFACE, EGL_FALSE);
-}
-
-EGLBoolean eglReleaseTexImage(
-        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->egl.eglReleaseTexImage) {
-        return s->cnx->egl.eglReleaseTexImage(
-                dp->disp[s->impl].dpy, s->surface, buffer);
-    }
-    return setError(EGL_BAD_SURFACE, EGL_FALSE);
-}
-
-EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglSwapInterval) {
-                if (cnx->egl.eglSwapInterval(
-                        dp->disp[i].dpy, interval) == EGL_FALSE) {
-                    res = EGL_FALSE;
-                }
-            }
-        }
-    }
-    return res;
-}
-
-
-// ----------------------------------------------------------------------------
-// EGL 1.2
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglWaitClient(void)
-{
-    clearError();
-
-    // could be called before eglInitialize(), but we wouldn't have a context
-    // then, and this function would return GL_TRUE, which isn't wrong.
-    EGLBoolean res = EGL_TRUE;
-    EGLContext ctx = getContext();
-    if (ctx) {
-        egl_context_t const * const c = get_context(ctx);
-        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (uint32_t(c->impl)>=2)
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        egl_connection_t* const cnx = &gEGLImpl[c->impl];
-        if (!cnx->dso) 
-            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (cnx->egl.eglWaitClient) {
-            res = cnx->egl.eglWaitClient();
-        } else {
-            res = cnx->egl.eglWaitGL();
-        }
-    }
-    return res;
-}
-
-EGLBoolean eglBindAPI(EGLenum api)
-{
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    }
-
-    // bind this API on all EGLs
-    EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglBindAPI) {
-                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
-                    res = EGL_FALSE;
-                }
-            }
-        }
-    }
-    return res;
-}
-
-EGLenum eglQueryAPI(void)
-{
-    clearError();
-
-    if (egl_init_drivers() == EGL_FALSE) {
-        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    }
-
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglQueryAPI) {
-                // the first one we find is okay, because they all
-                // should be the same
-                return cnx->egl.eglQueryAPI();
-            }
-        }
-    }
-    // or, it can only be OpenGL ES
-    return EGL_OPENGL_ES_API;
-}
-
-EGLBoolean eglReleaseThread(void)
-{
-    clearError();
-
-    // If there is context bound to the thread, release it
-    loseCurrent(get_context(getContext()));
-
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            if (cnx->egl.eglReleaseThread) {
-                cnx->egl.eglReleaseThread();
-            }
-        }
-    }
-    clearTLS();    
-    return EGL_TRUE;
-}
-
-EGLSurface eglCreatePbufferFromClientBuffer(
-          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
-          EGLConfig config, const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const* dp = 0;
-    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
-    if (!cnx) return EGL_FALSE;
-    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
-        return cnx->egl.eglCreatePbufferFromClientBuffer(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                buftype, buffer,
-                dp->configs[intptr_t(config)].config, attrib_list);
-    }
-    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
-}
-
-// ----------------------------------------------------------------------------
-// EGL_EGLEXT_VERSION 3
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
-        const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;
-
-    egl_surface_t const * const s = get_surface(surface);
-
-    if (s->cnx->egl.eglLockSurfaceKHR) {
-        return s->cnx->egl.eglLockSurfaceKHR(
-                dp->disp[s->impl].dpy, s->surface, attrib_list);
-    }
-    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-}
-
-EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(surface);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, surface))
-        return EGL_FALSE;
-
-    egl_surface_t const * const s = get_surface(surface);
-
-    if (s->cnx->egl.eglUnlockSurfaceKHR) {
-        return s->cnx->egl.eglUnlockSurfaceKHR(
-                dp->disp[s->impl].dpy, s->surface);
-    }
-    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-}
-
-EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
-        EGLClientBuffer buffer, const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_NO_IMAGE_KHR;
-
-    if (ctx != EGL_NO_CONTEXT) {
-        ContextRef _c(ctx);
-        if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
-        if (!validate_display_context(dpy, ctx))
-            return EGL_NO_IMAGE_KHR;
-        egl_context_t * const c = get_context(ctx);
-        // since we have an EGLContext, we know which implementation to use
-        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
-                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
-        if (image == EGL_NO_IMAGE_KHR)
-            return image;
-            
-        egl_image_t* result = new egl_image_t(dpy, ctx);
-        result->images[c->impl] = image;
-        return (EGLImageKHR)result;
-    } else {
-        // EGL_NO_CONTEXT is a valid parameter
-
-        /* Since we don't have a way to know which implementation to call,
-         * we're calling all of them. If at least one of the implementation
-         * succeeded, this is a success.
-         */
-
-        EGLint currentError = eglGetError();
-
-        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
-        bool success = false;
-        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-            egl_connection_t* const cnx = &gEGLImpl[i];
-            implImages[i] = EGL_NO_IMAGE_KHR;
-            if (cnx->dso) {
-                if (cnx->egl.eglCreateImageKHR) {
-                    implImages[i] = cnx->egl.eglCreateImageKHR(
-                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
-                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
-                        success = true;
-                    }
-                }
-            }
-        }
-
-        if (!success) {
-            // failure, if there was an error when we entered this function,
-            // the error flag must not be updated.
-            // Otherwise, the error is whatever happened in the implementation
-            // that faulted.
-            if (currentError != EGL_SUCCESS) {
-                setError(currentError, EGL_NO_IMAGE_KHR);
-            }
-            return EGL_NO_IMAGE_KHR;
-        } else {
-            // In case of success, we need to clear all error flags
-            // (especially those caused by the implementation that didn't
-            // succeed). TODO: we could avoid this if we knew this was
-            // a "full" success (all implementation succeeded).
-            eglGetError();
-        }
-
-        egl_image_t* result = new egl_image_t(dpy, ctx);
-        memcpy(result->images, implImages, sizeof(implImages));
-        return (EGLImageKHR)result;
-    }
-}
-
-EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    ImageRef _i(img);
-    if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-
-    egl_image_t* image = get_image(img);
-    bool success = false;
-    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
-        egl_connection_t* const cnx = &gEGLImpl[i];
-        if (image->images[i] != EGL_NO_IMAGE_KHR) {
-            if (cnx->dso) {
-                if (cnx->egl.eglDestroyImageKHR) {
-                    if (cnx->egl.eglDestroyImageKHR(
-                            dp->disp[i].dpy, image->images[i])) {
-                        success = true;
-                    }
-                }
-            }
-        }
-    }
-    if (!success)
-        return EGL_FALSE;
-
-    _i.terminate();
-
-    return EGL_TRUE;
-}
-
-// ----------------------------------------------------------------------------
-// EGL_EGLEXT_VERSION 5
-// ----------------------------------------------------------------------------
-
-
-EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_NO_SYNC_KHR;
-
-    EGLContext ctx = eglGetCurrentContext();
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_NO_SYNC_KHR;
-    egl_context_t * const c = get_context(ctx);
-    EGLSyncKHR result = EGL_NO_SYNC_KHR;
-    if (c->cnx->egl.eglCreateSyncKHR) {
-        EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
-                dp->disp[c->impl].dpy, type, attrib_list);
-        if (sync == EGL_NO_SYNC_KHR)
-            return sync;
-        result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
-    }
-    return (EGLSyncKHR)result;
-}
-
-EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SyncRef _s(sync);
-    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    egl_sync_t* syncObject = get_sync(sync);
-
-    EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-
-    EGLBoolean result = EGL_FALSE;
-    egl_context_t * const c = get_context(ctx);
-    if (c->cnx->egl.eglDestroySyncKHR) {
-        result = c->cnx->egl.eglDestroySyncKHR(
-                dp->disp[c->impl].dpy, syncObject->sync);
-        if (result)
-            _s.terminate();
-    }
-    return result;
-}
-
-EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SyncRef _s(sync);
-    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    egl_sync_t* syncObject = get_sync(sync);
-
-    EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-
-    egl_context_t * const c = get_context(ctx);
-
-    if (c->cnx->egl.eglClientWaitSyncKHR) {
-        return c->cnx->egl.eglClientWaitSyncKHR(
-                dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
-    }
-
-    return EGL_FALSE;
-}
-
-EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SyncRef _s(sync);
-    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-    egl_sync_t* syncObject = get_sync(sync);
-
-    EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
-    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;
-
-    egl_context_t * const c = get_context(ctx);
-
-    if (c->cnx->egl.eglGetSyncAttribKHR) {
-        return c->cnx->egl.eglGetSyncAttribKHR(
-                dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
-    }
-
-    return EGL_FALSE;
-}
-
-// ----------------------------------------------------------------------------
-// ANDROID extensions
-// ----------------------------------------------------------------------------
-
-EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
-        EGLint left, EGLint top, EGLint width, EGLint height)
-{
-    clearError();
-
-    egl_display_t const * const dp = validate_display(dpy);
-    if (!dp) return EGL_FALSE;
-
-    SurfaceRef _s(draw);
-    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-
-    if (!validate_display_surface(dpy, draw))
-        return EGL_FALSE;    
-    egl_surface_t const * const s = get_surface(draw);
-    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
-        return s->cnx->egl.eglSetSwapRectangleANDROID(
-                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
-    }
-    return setError(EGL_BAD_DISPLAY, NULL);
-}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
new file mode 100644
index 0000000..7d5d010
--- /dev/null
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -0,0 +1,1440 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <hardware/gralloc.h>
+#include <system/window.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <cutils/memory.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+
+#include "egl_impl.h"
+#include "egl_tls.h"
+#include "glesv2dbg.h"
+#include "hooks.h"
+
+#include "egl_display.h"
+#include "egl_impl.h"
+#include "egl_object.h"
+#include "egl_tls.h"
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+static char const * const sVendorString     = "Android";
+static char const * const sVersionString    = "1.4 Android META-EGL";
+static char const * const sClientApiString  = "OpenGL ES";
+static char const * const sExtensionString  =
+        "EGL_KHR_image "
+        "EGL_KHR_image_base "
+        "EGL_KHR_image_pixmap "
+        "EGL_KHR_gl_texture_2D_image "
+        "EGL_KHR_gl_texture_cubemap_image "
+        "EGL_KHR_gl_renderbuffer_image "
+        "EGL_KHR_fence_sync "
+        "EGL_ANDROID_image_native_buffer "
+        "EGL_ANDROID_swap_rectangle "
+        ;
+
+struct extention_map_t {
+    const char* name;
+    __eglMustCastToProperFunctionPointerType address;
+};
+
+static const extention_map_t sExtentionMap[] = {
+    { "eglLockSurfaceKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
+    { "eglUnlockSurfaceKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
+    { "eglCreateImageKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
+    { "eglDestroyImageKHR",
+            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
+    { "eglSetSwapRectangleANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
+};
+
+// accesses protected by sExtensionMapMutex
+static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+static int sGLExtentionSlot = 0;
+static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void(*findProcAddress(const char* name,
+        const extention_map_t* map, size_t n))() {
+    for (uint32_t i=0 ; i<n ; i++) {
+        if (!strcmp(name, map[i].name)) {
+            return map[i].address;
+        }
+    }
+    return NULL;
+}
+
+// ----------------------------------------------------------------------------
+
+template<typename T>
+static __attribute__((noinline))
+int binarySearch(T const sortedArray[], int first, int last, T key) {
+    while (first <= last) {
+        int mid = (first + last) / 2;
+        if (sortedArray[mid] < key) {
+            first = mid + 1;
+        } else if (key < sortedArray[mid]) {
+            last = mid - 1;
+        } else {
+            return mid;
+        }
+    }
+    return -1;
+}
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
+extern EGLBoolean egl_init_drivers();
+extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
+extern int gEGLDebugLevel;
+extern gl_hooks_t gHooksTrace;
+extern gl_hooks_t gHooksDebug;
+} // namespace android;
+
+// ----------------------------------------------------------------------------
+
+static inline void clearError() { egl_tls_t::clearError(); }
+static inline EGLContext getContext() { return egl_tls_t::getContext(); }
+
+// ----------------------------------------------------------------------------
+
+EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
+{
+    clearError();
+
+    uint32_t index = uint32_t(display);
+    if (index >= NUM_DISPLAYS) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
+    return dpy;
+}
+
+// ----------------------------------------------------------------------------
+// Initialization
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+    clearError();
+
+    egl_display_t * const dp = get_display(dpy);
+    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean res = dp->initialize(major, minor);
+
+    return res;
+}
+
+EGLBoolean eglTerminate(EGLDisplay dpy)
+{
+    // NOTE: don't unload the drivers b/c some APIs can be called
+    // after eglTerminate() has been called. eglTerminate() only
+    // terminates an EGLDisplay, not a EGL itself.
+
+    clearError();
+
+    egl_display_t* const dp = get_display(dpy);
+    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    EGLBoolean res = dp->terminate();
+    
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+// configuration
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglGetConfigs(   EGLDisplay dpy,
+                            EGLConfig *configs,
+                            EGLint config_size, EGLint *num_config)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    GLint numConfigs = dp->numTotalConfigs;
+    if (!configs) {
+        *num_config = numConfigs;
+        return EGL_TRUE;
+    }
+
+    GLint n = 0;
+    for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
+        *configs++ = EGLConfig(i);
+        config_size--;
+        n++;
+    }
+    
+    *num_config = n;
+    return EGL_TRUE;
+}
+
+EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
+                            EGLConfig *configs, EGLint config_size,
+                            EGLint *num_config)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    if (num_config==0) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    EGLint n;
+    EGLBoolean res = EGL_FALSE;
+    *num_config = 0;
+
+    
+    // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 
+    // to do this, we have to go through the attrib_list array once
+    // to figure out both its size and if it contains an EGL_CONFIG_ID
+    // key. If so, the full array is copied and patched.
+    // NOTE: we assume that there can be only one occurrence
+    // of EGL_CONFIG_ID.
+    
+    EGLint patch_index = -1;
+    GLint attr;
+    size_t size = 0;
+    if (attrib_list) {
+        while ((attr=attrib_list[size]) != EGL_NONE) {
+            if (attr == EGL_CONFIG_ID)
+                patch_index = size;
+            size += 2;
+        }
+    }
+    if (patch_index >= 0) {
+        size += 2; // we need copy the sentinel as well
+        EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
+        if (new_list == 0)
+            return setError(EGL_BAD_ALLOC, EGL_FALSE);
+        memcpy(new_list, attrib_list, size*sizeof(EGLint));
+
+        // patch the requested EGL_CONFIG_ID
+        bool found = false;
+        EGLConfig ourConfig(0);
+        EGLint& configId(new_list[patch_index+1]);
+        for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
+            if (dp->configs[i].configId == configId) {
+                ourConfig = EGLConfig(i);
+                configId = dp->configs[i].implConfigId;
+                found = true;
+                break;
+            }
+        }
+
+        egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
+        if (found && cnx->dso) {
+            // and switch to the new list
+            attrib_list = const_cast<const EGLint *>(new_list);
+
+            // At this point, the only configuration that can match is
+            // dp->configs[i][index], however, we don't know if it would be
+            // rejected because of the other attributes, so we do have to call
+            // cnx->egl.eglChooseConfig() -- but we don't have to loop
+            // through all the EGLimpl[].
+            // We also know we can only get a single config back, and we know
+            // which one.
+
+            res = cnx->egl.eglChooseConfig(
+                    dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
+                    attrib_list, configs, config_size, &n);
+            if (res && n>0) {
+                // n has to be 0 or 1, by construction, and we already know
+                // which config it will return (since there can be only one).
+                if (configs) {
+                    configs[0] = ourConfig;
+                }
+                *num_config = 1;
+            }
+        }
+
+        free(const_cast<EGLint *>(attrib_list));
+        return res;
+    }
+
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglChooseConfig(
+                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
+                if (configs) {
+                    // now we need to convert these client EGLConfig to our
+                    // internal EGLConfig format.
+                    // This is done in O(n Log(n)) time.
+                    for (int j=0 ; j<n ; j++) {
+                        egl_config_t key(i, configs[j]);
+                        intptr_t index = binarySearch<egl_config_t>(
+                                dp->configs, 0, dp->numTotalConfigs, key);
+                        if (index >= 0) {
+                            configs[j] = EGLConfig(index);
+                        } else {
+                            return setError(EGL_BAD_CONFIG, EGL_FALSE);
+                        }
+                    }
+                    configs += n;
+                    config_size -= n;
+                }
+                *num_config += n;
+                res = EGL_TRUE;
+            }
+        }
+    }
+    return res;
+}
+
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+        EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (!cnx) return EGL_FALSE;
+    
+    if (attribute == EGL_CONFIG_ID) {
+        *value = dp->configs[intptr_t(config)].configId;
+        return EGL_TRUE;
+    }
+    return cnx->egl.eglGetConfigAttrib(
+            dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+            dp->configs[intptr_t(config)].config, attribute, value);
+}
+
+// ----------------------------------------------------------------------------
+// surfaces
+// ----------------------------------------------------------------------------
+
+EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
+                                    NativeWindowType window,
+                                    const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
+        EGLConfig iConfig = dp->configs[intptr_t(config)].config;
+        EGLint format;
+
+        // set the native window's buffers format to match this config
+        if (cnx->egl.eglGetConfigAttrib(iDpy,
+                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
+            if (format != 0) {
+                native_window_set_buffers_geometry(window, 0, 0, format);
+            }
+        }
+
+        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
+                iDpy, iConfig, window, attrib_list);
+        if (surface != EGL_NO_SURFACE) {
+            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
+                    dp->configs[intptr_t(config)].impl, cnx);
+            return s;
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
+                                    NativePixmapType pixmap,
+                                    const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                dp->configs[intptr_t(config)].config, pixmap, attrib_list);
+        if (surface != EGL_NO_SURFACE) {
+            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
+                    dp->configs[intptr_t(config)].impl, cnx);
+            return s;
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+
+EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
+                                    const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                dp->configs[intptr_t(config)].config, attrib_list);
+        if (surface != EGL_NO_SURFACE) {
+            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
+                    dp->configs[intptr_t(config)].impl, cnx);
+            return s;
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+                                    
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t * const s = get_surface(surface);
+    EGLBoolean result = s->cnx->egl.eglDestroySurface(
+            dp->disp[s->impl].dpy, s->surface);
+    if (result == EGL_TRUE) {
+        if (s->win != NULL) {
+            native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
+        }
+        _s.terminate();
+    }
+    return result;
+}
+
+EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
+                            EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    EGLBoolean result(EGL_TRUE);
+    if (attribute == EGL_CONFIG_ID) {
+        // We need to remap EGL_CONFIG_IDs
+        *value = dp->configs[intptr_t(s->config)].configId;
+    } else {
+        result = s->cnx->egl.eglQuerySurface(
+                dp->disp[s->impl].dpy, s->surface, attribute, value);
+    }
+
+    return result;
+}
+
+// ----------------------------------------------------------------------------
+// Contexts
+// ----------------------------------------------------------------------------
+
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
+                            EGLContext share_list, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (cnx) {
+        if (share_list != EGL_NO_CONTEXT) {
+            egl_context_t* const c = get_context(share_list);
+            share_list = c->context;
+        }
+        EGLContext context = cnx->egl.eglCreateContext(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                dp->configs[intptr_t(config)].config,
+                share_list, attrib_list);
+        if (context != EGL_NO_CONTEXT) {
+            // figure out if it's a GLESv1 or GLESv2
+            int version = 0;
+            if (attrib_list) {
+                while (*attrib_list != EGL_NONE) {
+                    GLint attr = *attrib_list++;
+                    GLint value = *attrib_list++;
+                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
+                        if (value == 1) {
+                            version = GLESv1_INDEX;
+                        } else if (value == 2) {
+                            version = GLESv2_INDEX;
+                        }
+                    }
+                };
+            }
+            egl_context_t* c = new egl_context_t(dpy, context, config,
+                    dp->configs[intptr_t(config)].impl, cnx, version);
+            return c;
+        }
+    }
+    return EGL_NO_CONTEXT;
+}
+
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp)
+        return EGL_FALSE;
+
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+    
+    egl_context_t * const c = get_context(ctx);
+    EGLBoolean result = c->cnx->egl.eglDestroyContext(
+            dp->disp[c->impl].dpy, c->context);
+    if (result == EGL_TRUE) {
+        _c.terminate();
+    }
+    return result;
+}
+
+static void loseCurrent(egl_context_t * cur_c)
+{
+    if (cur_c) {
+        egl_surface_t * cur_r = get_surface(cur_c->read);
+        egl_surface_t * cur_d = get_surface(cur_c->draw);
+
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        cur_c->read = NULL;
+        cur_c->draw = NULL;
+
+        _cur_c.release();
+        _cur_r.release();
+        _cur_d.release();
+    }
+}
+
+EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
+                            EGLSurface read, EGLContext ctx)
+{
+    clearError();
+
+    egl_display_t const * const dp = get_display(dpy);
+    if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
+    // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
+    // a valid but uninitialized display.
+    if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
+         (draw != EGL_NO_SURFACE) ) {
+        if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    // get a reference to the object passed in
+    ContextRef _c(ctx);
+    SurfaceRef _d(draw);
+    SurfaceRef _r(read);
+
+    // validate the context (if not EGL_NO_CONTEXT)
+    if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
+        // EGL_NO_CONTEXT is valid
+        return EGL_FALSE;
+    }
+
+    // these are the underlying implementation's object
+    EGLContext impl_ctx  = EGL_NO_CONTEXT;
+    EGLSurface impl_draw = EGL_NO_SURFACE;
+    EGLSurface impl_read = EGL_NO_SURFACE;
+
+    // these are our objects structs passed in
+    egl_context_t       * c = NULL;
+    egl_surface_t const * d = NULL;
+    egl_surface_t const * r = NULL;
+
+    // these are the current objects structs
+    egl_context_t * cur_c = get_context(getContext());
+    
+    if (ctx != EGL_NO_CONTEXT) {
+        c = get_context(ctx);
+        impl_ctx = c->context;
+    } else {
+        // no context given, use the implementation of the current context
+        if (cur_c == NULL) {
+            // no current context
+            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
+                // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
+                return setError(EGL_BAD_MATCH, EGL_FALSE);
+            }
+            // not an error, there is just no current context.
+            return EGL_TRUE;
+        }
+    }
+
+    // retrieve the underlying implementation's draw EGLSurface
+    if (draw != EGL_NO_SURFACE) {
+        d = get_surface(draw);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && d->impl != c->impl)
+            return setError(EGL_BAD_MATCH, EGL_FALSE);
+        impl_draw = d->surface;
+    }
+
+    // retrieve the underlying implementation's read EGLSurface
+    if (read != EGL_NO_SURFACE) {
+        r = get_surface(read);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && r->impl != c->impl)
+            return setError(EGL_BAD_MATCH, EGL_FALSE);
+        impl_read = r->surface;
+    }
+
+    EGLBoolean result;
+
+    if (c) {
+        result = c->cnx->egl.eglMakeCurrent(
+                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    } else {
+        result = cur_c->cnx->egl.eglMakeCurrent(
+                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    }
+
+    if (result == EGL_TRUE) {
+
+        loseCurrent(cur_c);
+
+        if (ctx != EGL_NO_CONTEXT) {
+            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
+            egl_tls_t::setContext(ctx);
+            if (gEGLDebugLevel > 0) {
+                CreateDbgContext(c->version, c->cnx->hooks[c->version]);
+            }
+            _c.acquire();
+            _r.acquire();
+            _d.acquire();
+            c->read = read;
+            c->draw = draw;
+        } else {
+            setGLHooksThreadSpecific(&gHooksNoContext);
+            egl_tls_t::setContext(EGL_NO_CONTEXT);
+        }
+    }
+    return result;
+}
+
+
+EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
+                            EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    ContextRef _c(ctx);
+    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    egl_context_t * const c = get_context(ctx);
+
+    EGLBoolean result(EGL_TRUE);
+    if (attribute == EGL_CONFIG_ID) {
+        *value = dp->configs[intptr_t(c->config)].configId;
+    } else {
+        // We need to remap EGL_CONFIG_IDs
+        result = c->cnx->egl.eglQueryContext(
+                dp->disp[c->impl].dpy, c->context, attribute, value);
+    }
+
+    return result;
+}
+
+EGLContext eglGetCurrentContext(void)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_CONTEXT.
+
+    clearError();
+
+    EGLContext ctx = getContext();
+    return ctx;
+}
+
+EGLSurface eglGetCurrentSurface(EGLint readdraw)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_SURFACE.
+
+    clearError();
+
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
+        switch (readdraw) {
+            case EGL_READ: return c->read;
+            case EGL_DRAW: return c->draw;            
+            default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        }
+    }
+    return EGL_NO_SURFACE;
+}
+
+EGLDisplay eglGetCurrentDisplay(void)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_DISPLAY.
+
+    clearError();
+
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
+        return c->dpy;
+    }
+    return EGL_NO_DISPLAY;
+}
+
+EGLBoolean eglWaitGL(void)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
+    clearError();
+
+    EGLBoolean res = EGL_TRUE;
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (uint32_t(c->impl)>=2)
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl[c->impl];
+        if (!cnx->dso) 
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        res = cnx->egl.eglWaitGL();
+    }
+    return res;
+}
+
+EGLBoolean eglWaitNative(EGLint engine)
+{
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
+    clearError();
+
+    EGLBoolean res = EGL_TRUE;
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (uint32_t(c->impl)>=2)
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl[c->impl];
+        if (!cnx->dso) 
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        res = cnx->egl.eglWaitNative(engine);
+    }
+    return res;
+}
+
+EGLint eglGetError(void)
+{
+    EGLint result = EGL_SUCCESS;
+    EGLint err;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        err = EGL_SUCCESS;
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso)
+            err = cnx->egl.eglGetError();
+        if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
+            result = err;
+    }
+    err = egl_tls_t::getError();
+    if (result == EGL_SUCCESS)
+        result = err;
+    return result;
+}
+
+// Note: Similar implementations of these functions also exist in
+// gl2.cpp and gl.cpp, and are used by applications that call the
+// exported entry points directly.
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
+static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
+
+static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage =
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    glEGLImageTargetTexture2DOES_impl(target, implImage);
+}
+
+static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage =
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
+}
+
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
+{
+    // eglGetProcAddress() could be the very first function called
+    // in which case we must make sure we've initialized ourselves, this
+    // happens the first time egl_get_display() is called.
+
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        setError(EGL_BAD_PARAMETER, NULL);
+        return  NULL;
+    }
+
+    __eglMustCastToProperFunctionPointerType addr;
+    addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap));
+    if (addr) return addr;
+
+    // this protects accesses to sGLExtentionMap and sGLExtentionSlot
+    pthread_mutex_lock(&sExtensionMapMutex);
+
+        /*
+         * Since eglGetProcAddress() is not associated to anything, it needs
+         * to return a function pointer that "works" regardless of what
+         * the current context is.
+         *
+         * For this reason, we return a "forwarder", a small stub that takes
+         * care of calling the function associated with the context
+         * currently bound.
+         *
+         * We first look for extensions we've already resolved, if we're seeing
+         * this extension for the first time, we go through all our
+         * implementations and call eglGetProcAddress() and record the
+         * result in the appropriate implementation hooks and return the
+         * address of the forwarder corresponding to that hook set.
+         *
+         */
+
+        const String8 name(procname);
+        addr = sGLExtentionMap.valueFor(name);
+        const int slot = sGLExtentionSlot;
+
+        LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
+                "no more slots for eglGetProcAddress(\"%s\")",
+                procname);
+
+        if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
+            bool found = false;
+            for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+                egl_connection_t* const cnx = &gEGLImpl[i];
+                if (cnx->dso && cnx->egl.eglGetProcAddress) {
+                    found = true;
+                    // Extensions are independent of the bound context
+                    cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
+                    cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
+#if EGL_TRACE
+                    gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
+#endif
+                            cnx->egl.eglGetProcAddress(procname);
+                }
+            }
+            if (found) {
+                addr = gExtensionForwarders[slot];
+
+                if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
+                    glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
+                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
+                }
+                if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
+                    glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
+                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
+                }
+
+                sGLExtentionMap.add(name, addr);
+                sGLExtentionSlot++;
+            }
+        }
+
+    pthread_mutex_unlock(&sExtensionMapMutex);
+    return addr;
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+    EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
+    if (gEGLDebugLevel > 0)
+        Debug_eglSwapBuffers(dpy, draw);
+
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(draw);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(draw);
+    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
+}
+
+EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
+                            NativePixmapType target)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    return s->cnx->egl.eglCopyBuffers(
+            dp->disp[s->impl].dpy, s->surface, target);
+}
+
+const char* eglQueryString(EGLDisplay dpy, EGLint name)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return (const char *) NULL;
+
+    switch (name) {
+        case EGL_VENDOR:
+            return sVendorString;
+        case EGL_VERSION:
+            return sVersionString;
+        case EGL_EXTENSIONS:
+            return sExtensionString;
+        case EGL_CLIENT_APIS:
+            return sClientApiString;
+    }
+    return setError(EGL_BAD_PARAMETER, (const char *)0);
+}
+
+
+// ----------------------------------------------------------------------------
+// EGL 1.1
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSurfaceAttrib(
+        EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglSurfaceAttrib) {
+        return s->cnx->egl.eglSurfaceAttrib(
+                dp->disp[s->impl].dpy, s->surface, attribute, value);
+    }
+    return setError(EGL_BAD_SURFACE, EGL_FALSE);
+}
+
+EGLBoolean eglBindTexImage(
+        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglBindTexImage) {
+        return s->cnx->egl.eglBindTexImage(
+                dp->disp[s->impl].dpy, s->surface, buffer);
+    }
+    return setError(EGL_BAD_SURFACE, EGL_FALSE);
+}
+
+EGLBoolean eglReleaseTexImage(
+        EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglReleaseTexImage) {
+        return s->cnx->egl.eglReleaseTexImage(
+                dp->disp[s->impl].dpy, s->surface, buffer);
+    }
+    return setError(EGL_BAD_SURFACE, EGL_FALSE);
+}
+
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    EGLBoolean res = EGL_TRUE;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglSwapInterval) {
+                if (cnx->egl.eglSwapInterval(
+                        dp->disp[i].dpy, interval) == EGL_FALSE) {
+                    res = EGL_FALSE;
+                }
+            }
+        }
+    }
+    return res;
+}
+
+
+// ----------------------------------------------------------------------------
+// EGL 1.2
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglWaitClient(void)
+{
+    clearError();
+
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+    EGLBoolean res = EGL_TRUE;
+    EGLContext ctx = getContext();
+    if (ctx) {
+        egl_context_t const * const c = get_context(ctx);
+        if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (uint32_t(c->impl)>=2)
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl[c->impl];
+        if (!cnx->dso) 
+            return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+        if (cnx->egl.eglWaitClient) {
+            res = cnx->egl.eglWaitClient();
+        } else {
+            res = cnx->egl.eglWaitGL();
+        }
+    }
+    return res;
+}
+
+EGLBoolean eglBindAPI(EGLenum api)
+{
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    // bind this API on all EGLs
+    EGLBoolean res = EGL_TRUE;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglBindAPI) {
+                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
+                    res = EGL_FALSE;
+                }
+            }
+        }
+    }
+    return res;
+}
+
+EGLenum eglQueryAPI(void)
+{
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglQueryAPI) {
+                // the first one we find is okay, because they all
+                // should be the same
+                return cnx->egl.eglQueryAPI();
+            }
+        }
+    }
+    // or, it can only be OpenGL ES
+    return EGL_OPENGL_ES_API;
+}
+
+EGLBoolean eglReleaseThread(void)
+{
+    clearError();
+
+    // If there is context bound to the thread, release it
+    loseCurrent(get_context(getContext()));
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso) {
+            if (cnx->egl.eglReleaseThread) {
+                cnx->egl.eglReleaseThread();
+            }
+        }
+    }
+    egl_tls_t::clearTLS();
+    dbgReleaseThread();
+    return EGL_TRUE;
+}
+
+EGLSurface eglCreatePbufferFromClientBuffer(
+          EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+          EGLConfig config, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const* dp = 0;
+    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
+    if (!cnx) return EGL_FALSE;
+    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
+        return cnx->egl.eglCreatePbufferFromClientBuffer(
+                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
+                buftype, buffer,
+                dp->configs[intptr_t(config)].config, attrib_list);
+    }
+    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
+}
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 3
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+        const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglLockSurfaceKHR) {
+        return s->cnx->egl.eglLockSurfaceKHR(
+                dp->disp[s->impl].dpy, s->surface, attrib_list);
+    }
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(surface);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(surface);
+    if (s->cnx->egl.eglUnlockSurfaceKHR) {
+        return s->cnx->egl.eglUnlockSurfaceKHR(
+                dp->disp[s->impl].dpy, s->surface);
+    }
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+        EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_NO_IMAGE_KHR;
+
+    if (ctx != EGL_NO_CONTEXT) {
+        ContextRef _c(ctx);
+        if (!_c.get())
+            return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+        egl_context_t * const c = get_context(ctx);
+        // since we have an EGLContext, we know which implementation to use
+        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
+                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
+        if (image == EGL_NO_IMAGE_KHR)
+            return image;
+            
+        egl_image_t* result = new egl_image_t(dpy, ctx);
+        result->images[c->impl] = image;
+        return (EGLImageKHR)result;
+    } else {
+        // EGL_NO_CONTEXT is a valid parameter
+
+        /* Since we don't have a way to know which implementation to call,
+         * we're calling all of them. If at least one of the implementation
+         * succeeded, this is a success.
+         */
+
+        EGLint currentError = eglGetError();
+
+        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
+        bool success = false;
+        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+            egl_connection_t* const cnx = &gEGLImpl[i];
+            implImages[i] = EGL_NO_IMAGE_KHR;
+            if (cnx->dso) {
+                if (cnx->egl.eglCreateImageKHR) {
+                    implImages[i] = cnx->egl.eglCreateImageKHR(
+                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
+                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
+                        success = true;
+                    }
+                }
+            }
+        }
+
+        if (!success) {
+            // failure, if there was an error when we entered this function,
+            // the error flag must not be updated.
+            // Otherwise, the error is whatever happened in the implementation
+            // that faulted.
+            if (currentError != EGL_SUCCESS) {
+                setError(currentError, EGL_NO_IMAGE_KHR);
+            }
+            return EGL_NO_IMAGE_KHR;
+        } else {
+            // In case of success, we need to clear all error flags
+            // (especially those caused by the implementation that didn't
+            // succeed). TODO: we could avoid this if we knew this was
+            // a "full" success (all implementation succeeded).
+            eglGetError();
+        }
+
+        egl_image_t* result = new egl_image_t(dpy, ctx);
+        memcpy(result->images, implImages, sizeof(implImages));
+        return (EGLImageKHR)result;
+    }
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    ImageRef _i(img);
+    if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    egl_image_t* image = get_image(img);
+    bool success = false;
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (image->images[i] != EGL_NO_IMAGE_KHR) {
+            if (cnx->dso) {
+                if (cnx->egl.eglDestroyImageKHR) {
+                    if (cnx->egl.eglDestroyImageKHR(
+                            dp->disp[i].dpy, image->images[i])) {
+                        success = true;
+                    }
+                }
+            }
+        }
+    }
+    if (!success)
+        return EGL_FALSE;
+
+    _i.terminate();
+
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 5
+// ----------------------------------------------------------------------------
+
+
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_NO_SYNC_KHR;
+
+    EGLContext ctx = eglGetCurrentContext();
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
+
+    egl_context_t * const c = get_context(ctx);
+    EGLSyncKHR result = EGL_NO_SYNC_KHR;
+    if (c->cnx->egl.eglCreateSyncKHR) {
+        EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
+                dp->disp[c->impl].dpy, type, attrib_list);
+        if (sync == EGL_NO_SYNC_KHR)
+            return sync;
+        result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
+    }
+    return (EGLSyncKHR)result;
+}
+
+EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SyncRef _s(sync);
+    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    egl_sync_t* syncObject = get_sync(sync);
+
+    EGLContext ctx = syncObject->context;
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    EGLBoolean result = EGL_FALSE;
+    egl_context_t * const c = get_context(ctx);
+    if (c->cnx->egl.eglDestroySyncKHR) {
+        result = c->cnx->egl.eglDestroySyncKHR(
+                dp->disp[c->impl].dpy, syncObject->sync);
+        if (result)
+            _s.terminate();
+    }
+    return result;
+}
+
+EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SyncRef _s(sync);
+    if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    egl_sync_t* syncObject = get_sync(sync);
+
+    EGLContext ctx = syncObject->context;
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    egl_context_t * const c = get_context(ctx);
+    if (c->cnx->egl.eglClientWaitSyncKHR) {
+        return c->cnx->egl.eglClientWaitSyncKHR(
+                dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
+    }
+
+    return EGL_FALSE;
+}
+
+EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SyncRef _s(sync);
+    if (!_s.get())
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    egl_sync_t* syncObject = get_sync(sync);
+    EGLContext ctx = syncObject->context;
+    ContextRef _c(ctx);
+    if (!_c.get())
+        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+    egl_context_t * const c = get_context(ctx);
+    if (c->cnx->egl.eglGetSyncAttribKHR) {
+        return c->cnx->egl.eglGetSyncAttribKHR(
+                dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
+    }
+
+    return EGL_FALSE;
+}
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+        EGLint left, EGLint top, EGLint width, EGLint height)
+{
+    clearError();
+
+    egl_display_t const * const dp = validate_display(dpy);
+    if (!dp) return EGL_FALSE;
+
+    SurfaceRef _s(draw);
+    if (!_s.get())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    egl_surface_t const * const s = get_surface(draw);
+    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
+        return s->cnx->egl.eglSetSwapRectangleANDROID(
+                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
+    }
+    return setError(EGL_BAD_DISPLAY, NULL);
+}
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
new file mode 100644
index 0000000..83aafa6
--- /dev/null
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -0,0 +1,276 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include "egl_display.h"
+#include "egl_object.h"
+#include "egl_tls.h"
+#include "egl_impl.h"
+#include "Loader.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+extern void initEglTraceLevel();
+extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
+
+static int cmp_configs(const void* a, const void *b) {
+    const egl_config_t& c0 = *(egl_config_t const *)a;
+    const egl_config_t& c1 = *(egl_config_t const *)b;
+    return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
+}
+
+// ----------------------------------------------------------------------------
+
+egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
+
+egl_display_t::egl_display_t() :
+    magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) {
+}
+
+egl_display_t::~egl_display_t() {
+    magic = 0;
+}
+
+egl_display_t* egl_display_t::get(EGLDisplay dpy) {
+    uintptr_t index = uintptr_t(dpy)-1U;
+    return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index];
+}
+
+void egl_display_t::addObject(egl_object_t* object) {
+    Mutex::Autolock _l(lock);
+    objects.add(object);
+}
+
+void egl_display_t::removeObject(egl_object_t* object) {
+    Mutex::Autolock _l(lock);
+    objects.remove(object);
+}
+
+bool egl_display_t::getObject(egl_object_t* object) {
+    Mutex::Autolock _l(lock);
+    if (objects.indexOf(object) >= 0) {
+        object->incRef();
+        return true;
+    }
+    return false;
+}
+
+EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
+    if (uintptr_t(disp) >= NUM_DISPLAYS)
+        return NULL;
+
+    return sDisplay[uintptr_t(disp)].getDisplay(disp);
+}
+
+EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
+
+    Mutex::Autolock _l(lock);
+
+    // get our driver loader
+    Loader& loader(Loader::getInstance());
+
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso && disp[i].dpy == EGL_NO_DISPLAY) {
+            EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
+            disp[i].dpy = dpy;
+            if (dpy == EGL_NO_DISPLAY) {
+                loader.close(cnx->dso);
+                cnx->dso = NULL;
+            }
+        }
+    }
+
+    return EGLDisplay(uintptr_t(display) + 1U);
+}
+
+EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
+
+    Mutex::Autolock _l(lock);
+
+    if (refs > 0) {
+        if (major != NULL)
+            *major = VERSION_MAJOR;
+        if (minor != NULL)
+            *minor = VERSION_MINOR;
+        refs++;
+        return EGL_TRUE;
+    }
+
+#if EGL_TRACE
+
+    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
+    // the information from that call may be stale.)
+    initEglTraceLevel();
+
+#endif
+
+    setGLHooksThreadSpecific(&gHooksNoContext);
+
+    // initialize each EGL and
+    // build our own extension string first, based on the extension we know
+    // and the extension supported by our client implementation
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        cnx->major = -1;
+        cnx->minor = -1;
+        if (!cnx->dso)
+            continue;
+
+#if defined(ADRENO130)
+#warning "Adreno-130 eglInitialize() workaround"
+        /*
+         * The ADRENO 130 driver returns a different EGLDisplay each time
+         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
+         * after eglTerminate() has been called, so that eglInitialize()
+         * cannot be called again. Therefore, we need to make sure to call
+         * eglGetDisplay() before calling eglInitialize();
+         */
+        if (i == IMPL_HARDWARE) {
+            disp[i].dpy =
+            cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        }
+#endif
+
+        EGLDisplay idpy = disp[i].dpy;
+        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
+            //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
+            //        i, idpy, cnx->major, cnx->minor, cnx);
+
+            // display is now initialized
+            disp[i].state = egl_display_t::INITIALIZED;
+
+            // get the query-strings for this display for each implementation
+            disp[i].queryString.vendor = cnx->egl.eglQueryString(idpy,
+                    EGL_VENDOR);
+            disp[i].queryString.version = cnx->egl.eglQueryString(idpy,
+                    EGL_VERSION);
+            disp[i].queryString.extensions = cnx->egl.eglQueryString(idpy,
+                    EGL_EXTENSIONS);
+            disp[i].queryString.clientApi = cnx->egl.eglQueryString(idpy,
+                    EGL_CLIENT_APIS);
+
+        } else {
+            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
+                    egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+        }
+    }
+
+    EGLBoolean res = EGL_FALSE;
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
+            EGLint n;
+            if (cnx->egl.eglGetConfigs(disp[i].dpy, 0, 0, &n)) {
+                disp[i].config = (EGLConfig*) malloc(sizeof(EGLConfig) * n);
+                if (disp[i].config) {
+                    if (cnx->egl.eglGetConfigs(disp[i].dpy, disp[i].config, n,
+                            &disp[i].numConfigs)) {
+                        numTotalConfigs += n;
+                        res = EGL_TRUE;
+                    }
+                }
+            }
+        }
+    }
+
+    if (res == EGL_TRUE) {
+        configs = new egl_config_t[numTotalConfigs];
+        for (int i = 0, k = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+            egl_connection_t* const cnx = &gEGLImpl[i];
+            if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
+                for (int j = 0; j < disp[i].numConfigs; j++) {
+                    configs[k].impl = i;
+                    configs[k].config = disp[i].config[j];
+                    configs[k].configId = k + 1; // CONFIG_ID start at 1
+                    // store the implementation's CONFIG_ID
+                    cnx->egl.eglGetConfigAttrib(disp[i].dpy, disp[i].config[j],
+                            EGL_CONFIG_ID, &configs[k].implConfigId);
+                    k++;
+                }
+            }
+        }
+
+        // sort our configurations so we can do binary-searches
+        qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs);
+
+        refs++;
+        if (major != NULL)
+            *major = VERSION_MAJOR;
+        if (minor != NULL)
+            *minor = VERSION_MINOR;
+        return EGL_TRUE;
+    }
+    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+}
+
+EGLBoolean egl_display_t::terminate() {
+
+    Mutex::Autolock _l(lock);
+
+    if (refs == 0) {
+        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    // this is specific to Android, display termination is ref-counted.
+    if (refs > 1) {
+        refs--;
+        return EGL_TRUE;
+    }
+
+    EGLBoolean res = EGL_FALSE;
+    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
+        egl_connection_t* const cnx = &gEGLImpl[i];
+        if (cnx->dso && disp[i].state == egl_display_t::INITIALIZED) {
+            if (cnx->egl.eglTerminate(disp[i].dpy) == EGL_FALSE) {
+                LOGW("%d: eglTerminate(%p) failed (%s)", i, disp[i].dpy,
+                        egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
+            }
+            // REVISIT: it's unclear what to do if eglTerminate() fails
+            free(disp[i].config);
+
+            disp[i].numConfigs = 0;
+            disp[i].config = 0;
+            disp[i].state = egl_display_t::TERMINATED;
+
+            res = EGL_TRUE;
+        }
+    }
+
+    // Mark all objects remaining in the list as terminated, unless
+    // there are no reference to them, it which case, we're free to
+    // delete them.
+    size_t count = objects.size();
+    LOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
+    for (size_t i=0 ; i<count ; i++) {
+        egl_object_t* o = objects.itemAt(i);
+        o->destroy();
+    }
+
+    // this marks all object handles are "terminated"
+    objects.clear();
+
+    refs--;
+    numTotalConfigs = 0;
+    delete[] configs;
+    return res;
+}
+
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
new file mode 100644
index 0000000..8c482c3
--- /dev/null
+++ b/opengl/libs/EGL/egl_display.h
@@ -0,0 +1,143 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_DISPLAY_H
+#define ANDROID_EGL_DISPLAY_H
+
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+#include "hooks.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class egl_object_t;
+class egl_connection_t;
+
+// ----------------------------------------------------------------------------
+
+struct egl_config_t {
+    egl_config_t() {}
+    egl_config_t(int impl, EGLConfig config)
+        : impl(impl), config(config), configId(0), implConfigId(0) { }
+    int         impl;           // the implementation this config is for
+    EGLConfig   config;         // the implementation's EGLConfig
+    EGLint      configId;       // our CONFIG_ID
+    EGLint      implConfigId;   // the implementation's CONFIG_ID
+    inline bool operator < (const egl_config_t& rhs) const {
+        if (impl < rhs.impl) return true;
+        if (impl > rhs.impl) return false;
+        return config < rhs.config;
+    }
+};
+
+// ----------------------------------------------------------------------------
+
+class egl_display_t {
+    static egl_display_t sDisplay[NUM_DISPLAYS];
+    EGLDisplay getDisplay(EGLNativeDisplayType display);
+
+public:
+    enum {
+        NOT_INITIALIZED = 0,
+        INITIALIZED     = 1,
+        TERMINATED      = 2
+    };
+
+    egl_display_t();
+    ~egl_display_t();
+
+    EGLBoolean initialize(EGLint *major, EGLint *minor);
+    EGLBoolean terminate();
+
+    // add object to this display's list
+    void addObject(egl_object_t* object);
+    // remove object from this display's list
+    void removeObject(egl_object_t* object);
+    // add reference to this object. returns true if this is a valid object.
+    bool getObject(egl_object_t* object);
+
+
+    static egl_display_t* get(EGLDisplay dpy);
+    static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp);
+
+    inline bool isReady() const { return (refs > 0); }
+    inline bool isValid() const { return magic == '_dpy'; }
+    inline bool isAlive() const { return isValid(); }
+
+    struct strings_t {
+        char const * vendor;
+        char const * version;
+        char const * clientApi;
+        char const * extensions;
+    };
+
+    struct DisplayImpl {
+        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
+                        state(NOT_INITIALIZED), numConfigs(0) { }
+        EGLDisplay  dpy;
+        EGLConfig*  config;
+        EGLint      state;
+        EGLint      numConfigs;
+        strings_t   queryString;
+    };
+
+private:
+    uint32_t        magic;
+
+public:
+    DisplayImpl     disp[IMPL_NUM_IMPLEMENTATIONS];
+    EGLint          numTotalConfigs;
+    egl_config_t*   configs;
+
+private:
+    uint32_t        refs;
+    Mutex           lock;
+    SortedVector<egl_object_t*> objects;
+};
+
+// ----------------------------------------------------------------------------
+
+inline egl_display_t* get_display(EGLDisplay dpy) {
+    return egl_display_t::get(dpy);
+}
+
+// ----------------------------------------------------------------------------
+
+egl_display_t* validate_display(EGLDisplay dpy);
+egl_connection_t* validate_display_config(EGLDisplay dpy,
+        EGLConfig config, egl_display_t const*& dp);
+EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx);
+EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface);
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_EGL_DISPLAY_H
+
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
new file mode 100644
index 0000000..dbf9a01
--- /dev/null
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -0,0 +1,66 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/threads.h>
+
+#include "egl_object.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+egl_object_t::egl_object_t(egl_display_t* disp) :
+    display(disp), count(1) {
+    // NOTE: this does an implicit incRef
+    display->addObject(this);
+}
+
+egl_object_t::~egl_object_t() {
+}
+
+void egl_object_t::terminate() {
+    // this marks the object as "terminated"
+    display->removeObject(this);
+    if (decRef() == 1) {
+        // shouldn't happen because this is called from LocalRef
+        LOGE("egl_object_t::terminate() removed the last reference!");
+    }
+}
+
+void egl_object_t::destroy() {
+    if (decRef() == 1) {
+        delete this;
+    }
+}
+
+bool egl_object_t::get() {
+    // used by LocalRef, this does an incRef() atomically with
+    // checking that the object is valid.
+    return display->getObject(this);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
new file mode 100644
index 0000000..3459a8a
--- /dev/null
+++ b/opengl/libs/EGL/egl_object.h
@@ -0,0 +1,235 @@
+/* 
+ ** Copyright 2007, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_OBJECT_H
+#define ANDROID_EGL_OBJECT_H
+
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/threads.h>
+
+#include <system/window.h>
+
+#include "egl_display.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+struct egl_display_t;
+
+class egl_object_t {
+    egl_display_t *display;
+    mutable volatile int32_t count;
+
+protected:
+    virtual ~egl_object_t();
+
+public:
+    egl_object_t(egl_display_t* display);
+    void destroy();
+
+    inline int32_t incRef() { return android_atomic_inc(&count); }
+    inline int32_t decRef() { return android_atomic_dec(&count); }
+
+private:
+    void terminate();
+    bool get();
+
+public:
+    template <typename N, typename T>
+    class LocalRef {
+        egl_object_t* ref;
+        LocalRef();
+        LocalRef(const LocalRef* rhs);
+    public:
+        ~LocalRef();
+        explicit LocalRef(egl_object_t* rhs);
+        explicit LocalRef(T o) : ref(0) {
+            egl_object_t* native = reinterpret_cast<N*>(o);
+            if (o && native->get()) {
+                ref = native;
+            }
+        }
+        inline N* get() {
+            return static_cast<N*>(ref);
+        }
+        void acquire() const;
+        void release() const;
+        void terminate();
+    };
+    template <typename N, typename T>
+    friend class LocalRef;
+};
+
+template<typename N, typename T>
+egl_object_t::LocalRef<N, T>::LocalRef(egl_object_t* rhs) : ref(rhs) {
+    if (ref) {
+        ref->incRef();
+    }
+}
+
+template <typename N, typename T>
+egl_object_t::LocalRef<N,T>::~LocalRef() {
+    if (ref) {
+        ref->destroy();
+    }
+}
+
+template <typename N, typename T>
+void egl_object_t::LocalRef<N,T>::acquire() const {
+    if (ref) {
+        ref->incRef();
+    }
+}
+
+template <typename N, typename T>
+void egl_object_t::LocalRef<N,T>::release() const {
+    if (ref) {
+        if (ref->decRef() == 1) {
+            // shouldn't happen because this is called from LocalRef
+            LOGE("LocalRef::release() removed the last reference!");
+        }
+    }
+}
+
+template <typename N, typename T>
+void egl_object_t::LocalRef<N,T>::terminate() {
+    if (ref) {
+        ref->terminate();
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+class egl_surface_t: public egl_object_t {
+protected:
+    ~egl_surface_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
+
+    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
+            EGLSurface surface, int impl, egl_connection_t const* cnx) :
+        egl_object_t(get_display(dpy)), dpy(dpy), surface(surface),
+                config(config), win(win), impl(impl), cnx(cnx) {
+    }
+    EGLDisplay dpy;
+    EGLSurface surface;
+    EGLConfig config;
+    sp<ANativeWindow> win;
+    int impl;
+    egl_connection_t const* cnx;
+};
+
+class egl_context_t: public egl_object_t {
+protected:
+    ~egl_context_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
+
+    egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
+            int impl, egl_connection_t const* cnx, int version) :
+        egl_object_t(get_display(dpy)), dpy(dpy), context(context),
+                config(config), read(0), draw(0), impl(impl), cnx(cnx),
+                version(version) {
+    }
+    EGLDisplay dpy;
+    EGLContext context;
+    EGLConfig config;
+    EGLSurface read;
+    EGLSurface draw;
+    int impl;
+    egl_connection_t const* cnx;
+    int version;
+};
+
+class egl_image_t: public egl_object_t {
+protected:
+    ~egl_image_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
+
+    egl_image_t(EGLDisplay dpy, EGLContext context) :
+        egl_object_t(get_display(dpy)), dpy(dpy), context(context) {
+        memset(images, 0, sizeof(images));
+    }
+    EGLDisplay dpy;
+    EGLContext context;
+    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
+};
+
+class egl_sync_t: public egl_object_t {
+protected:
+    ~egl_sync_t() {}
+public:
+    typedef egl_object_t::LocalRef<egl_sync_t, EGLSyncKHR> Ref;
+
+    egl_sync_t(EGLDisplay dpy, EGLContext context, EGLSyncKHR sync) :
+        egl_object_t(get_display(dpy)), dpy(dpy), context(context), sync(sync) {
+    }
+    EGLDisplay dpy;
+    EGLContext context;
+    EGLSyncKHR sync;
+};
+
+// ----------------------------------------------------------------------------
+
+typedef egl_surface_t::Ref  SurfaceRef;
+typedef egl_context_t::Ref  ContextRef;
+typedef egl_image_t::Ref    ImageRef;
+typedef egl_sync_t::Ref     SyncRef;
+
+// ----------------------------------------------------------------------------
+
+template<typename NATIVE, typename EGL>
+static inline NATIVE* egl_to_native_cast(EGL arg) {
+    return reinterpret_cast<NATIVE*>(arg);
+}
+
+static inline
+egl_surface_t* get_surface(EGLSurface surface) {
+    return egl_to_native_cast<egl_surface_t>(surface);
+}
+
+static inline
+egl_context_t* get_context(EGLContext context) {
+    return egl_to_native_cast<egl_context_t>(context);
+}
+
+static inline
+egl_image_t* get_image(EGLImageKHR image) {
+    return egl_to_native_cast<egl_image_t>(image);
+}
+
+static inline
+egl_sync_t* get_sync(EGLSyncKHR sync) {
+    return egl_to_native_cast<egl_sync_t>(sync);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif // ANDROID_EGL_OBJECT_H
+
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
new file mode 100644
index 0000000..961a61e
--- /dev/null
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -0,0 +1,133 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <pthread.h>
+
+#include <cutils/log.h>
+
+#include <EGL/egl.h>
+
+#include "egl_tls.h"
+
+
+namespace android {
+
+pthread_key_t egl_tls_t::sKey = -1;
+pthread_mutex_t egl_tls_t::sLockKey = PTHREAD_MUTEX_INITIALIZER;
+
+egl_tls_t::egl_tls_t()
+    : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE), dbg(0) {
+}
+
+const char *egl_tls_t::egl_strerror(EGLint err) {
+    switch (err) {
+        case EGL_SUCCESS:               return "EGL_SUCCESS";
+        case EGL_NOT_INITIALIZED:       return "EGL_NOT_INITIALIZED";
+        case EGL_BAD_ACCESS:            return "EGL_BAD_ACCESS";
+        case EGL_BAD_ALLOC:             return "EGL_BAD_ALLOC";
+        case EGL_BAD_ATTRIBUTE:         return "EGL_BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG:            return "EGL_BAD_CONFIG";
+        case EGL_BAD_CONTEXT:           return "EGL_BAD_CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE:   return "EGL_BAD_CURRENT_SURFACE";
+        case EGL_BAD_DISPLAY:           return "EGL_BAD_DISPLAY";
+        case EGL_BAD_MATCH:             return "EGL_BAD_MATCH";
+        case EGL_BAD_NATIVE_PIXMAP:     return "EGL_BAD_NATIVE_PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW:     return "EGL_BAD_NATIVE_WINDOW";
+        case EGL_BAD_PARAMETER:         return "EGL_BAD_PARAMETER";
+        case EGL_BAD_SURFACE:           return "EGL_BAD_SURFACE";
+        case EGL_CONTEXT_LOST:          return "EGL_CONTEXT_LOST";
+        default: return "UNKNOWN";
+    }
+}
+
+void egl_tls_t::validateTLSKey()
+{
+    if (sKey == -1) {
+        pthread_mutex_lock(&sLockKey);
+        if (sKey == -1)
+            pthread_key_create(&sKey, NULL);
+        pthread_mutex_unlock(&sLockKey);
+    }
+}
+
+void egl_tls_t::setErrorEtcImpl(const char* caller, int line, EGLint error) {
+    validateTLSKey();
+    egl_tls_t* tls = getTLS();
+    if (tls->error != error) {
+        LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error));
+        tls->error = error;
+    }
+}
+
+bool egl_tls_t::logNoContextCall() {
+    egl_tls_t* tls = getTLS();
+    if (tls->logCallWithNoContext == true) {
+        tls->logCallWithNoContext = false;
+        return true;
+    }
+    return false;
+}
+
+egl_tls_t* egl_tls_t::getTLS() {
+    egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
+    if (tls == 0) {
+        tls = new egl_tls_t;
+        pthread_setspecific(sKey, tls);
+    }
+    return tls;
+}
+
+void egl_tls_t::clearTLS() {
+    if (sKey != -1) {
+        egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
+        if (tls) {
+            delete tls;
+            pthread_setspecific(sKey, 0);
+        }
+    }
+}
+
+void egl_tls_t::clearError() {
+    // This must clear the error from all the underlying EGL implementations as
+    // well as the EGL wrapper layer.
+    eglGetError();
+}
+
+EGLint egl_tls_t::getError() {
+    if (sKey == -1)
+        return EGL_SUCCESS;
+    egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
+    if (!tls) return EGL_SUCCESS;
+    EGLint error = tls->error;
+    tls->error = EGL_SUCCESS;
+    return error;
+}
+
+void egl_tls_t::setContext(EGLContext ctx) {
+    validateTLSKey();
+    getTLS()->ctx = ctx;
+}
+
+EGLContext egl_tls_t::getContext() {
+    if (sKey == -1)
+        return EGL_NO_CONTEXT;
+    egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey);
+    if (!tls) return EGL_NO_CONTEXT;
+    return tls->ctx;
+}
+
+
+} // namespace android
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
new file mode 100644
index 0000000..8b31468
--- /dev/null
+++ b/opengl/libs/EGL/egl_tls.h
@@ -0,0 +1,63 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_TLS_H
+#define ANDROID_EGL_TLS_H
+
+#include <pthread.h>
+
+#include <EGL/egl.h>
+
+namespace android {
+
+class DbgContext;
+
+class egl_tls_t {
+    static pthread_key_t sKey;
+    static pthread_mutex_t sLockKey;
+
+    EGLint      error;
+    EGLContext  ctx;
+    EGLBoolean  logCallWithNoContext;
+    DbgContext* dbg;
+
+    egl_tls_t();
+    static void validateTLSKey();
+    static void setErrorEtcImpl(const char* caller, int line, EGLint error);
+
+public:
+    static egl_tls_t* getTLS();
+    static void clearTLS();
+    static void clearError();
+    static EGLint getError();
+    static void setContext(EGLContext ctx);
+    static EGLContext getContext();
+    static bool logNoContextCall();
+    static const char *egl_strerror(EGLint err);
+
+    template<typename T>
+    static T setErrorEtc(const char* caller,
+            int line, EGLint error, T returnValue) {
+        setErrorEtcImpl(caller, line, error);
+        return returnValue;
+    }
+};
+
+#define setError(_e, _r) egl_tls_t::setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
+
+}; // namespace android
+
+#endif // ANDROID_EGL_TLS_H
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
index 7f5b27b..ff9be3c 100644
--- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -15,22 +15,18 @@
  */
 
 #include "header.h"
-#include "egl_tls.h"
 
-extern "C"
-{
+extern "C" {
 #include "liblzf/lzf.h"
 }
 
-namespace android
-{
+namespace android {
 
-pthread_key_t dbgEGLThreadLocalStorageKey = -1;
+static pthread_key_t dbgEGLThreadLocalStorageKey = -1;
+static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 
-DbgContext * getDbgContextThreadSpecific()
-{
-    tls_t* tls = (tls_t*)pthread_getspecific(dbgEGLThreadLocalStorageKey);
-    return tls->dbg;
+DbgContext * getDbgContextThreadSpecific() {
+    return (DbgContext*)pthread_getspecific(dbgEGLThreadLocalStorageKey);
 }
 
 DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks,
@@ -60,10 +56,13 @@
     free(lzf_ref[1]);
 }
 
-DbgContext * CreateDbgContext(const pthread_key_t EGLThreadLocalStorageKey,
-                              const unsigned version, const gl_hooks_t * const hooks)
+DbgContext* CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks)
 {
-    dbgEGLThreadLocalStorageKey = EGLThreadLocalStorageKey;
+    pthread_mutex_lock(&gThreadLocalStorageKeyMutex);
+    if (dbgEGLThreadLocalStorageKey == -1)
+        pthread_key_create(&dbgEGLThreadLocalStorageKey, NULL);
+    pthread_mutex_unlock(&gThreadLocalStorageKeyMutex);
+
     assert(version < 2);
     assert(GL_NO_ERROR == hooks->gl.glGetError());
     GLint MAX_VERTEX_ATTRIBS = 0;
@@ -71,7 +70,7 @@
     GLint readFormat, readType;
     hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
     hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
-    DbgContext * const dbg = new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS, readFormat, readType);
+    DbgContext* dbg = new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS, readFormat, readType);
 
     glesv2debugger::Message msg, cmd;
     msg.set_context_id(reinterpret_cast<int>(dbg));
@@ -88,12 +87,13 @@
     msg.set_arg0(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
     msg.set_arg1(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
     Send(msg, cmd);
+
+    *(DbgContext **)pthread_getspecific(dbgEGLThreadLocalStorageKey) = dbg;
     return dbg;
 }
 
-void DestroyDbgContext(DbgContext * const dbg)
-{
-    delete dbg;
+void dbgReleaseThread() {
+    delete getDbgContextThreadSpecific();
 }
 
 unsigned GetBytesPerPixel(const GLenum format, const GLenum type)
diff --git a/opengl/libs/GLES2_dbg/test/test_server.cpp b/opengl/libs/GLES2_dbg/test/test_server.cpp
index b6401e0..bbbe913 100644
--- a/opengl/libs/GLES2_dbg/test/test_server.cpp
+++ b/opengl/libs/GLES2_dbg/test/test_server.cpp
@@ -16,14 +16,12 @@
 
 #include "header.h"
 #include "gtest/gtest.h"
-#include "egl_tls.h"
 #include "hooks.h"
 
 namespace android
 {
 extern FILE * file;
 extern unsigned int MAX_FILE_SIZE;
-extern pthread_key_t dbgEGLThreadLocalStorageKey;
 };
 
 // tmpfile fails, so need to manually make a writable file first
@@ -114,7 +112,7 @@
     };
     hooks.gl.glGetError = HookMock::GetError;
     hooks.gl.glGetIntegerv = HookMock::GetIntegerv;
-    DbgContext * const dbg = CreateDbgContext(-1, 1, &hooks);
+    DbgContext * const dbg = CreateDbgContext(1, &hooks);
     ASSERT_TRUE(dbg != NULL);
     EXPECT_TRUE(dbg->vertexAttribs != NULL);
 
@@ -132,7 +130,7 @@
         EXPECT_EQ(expectedConstant, read.arg1());
     }
     CheckNoAvailable();
-    DestroyDbgContext(dbg);
+    dbgReleaseThread();
 }
 
 void * glNoop()
@@ -143,7 +141,7 @@
 class ServerFileContextTest : public ServerFileTest
 {
 protected:
-    tls_t tls;
+    DbgContext* dbg;
     gl_hooks_t hooks;
 
     ServerFileContextTest() { }
@@ -153,12 +151,8 @@
     virtual void SetUp() {
         ServerFileTest::SetUp();
 
-        if (dbgEGLThreadLocalStorageKey == -1)
-            pthread_key_create(&dbgEGLThreadLocalStorageKey, NULL);
-        ASSERT_NE(-1, dbgEGLThreadLocalStorageKey);
-        tls.dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
-        ASSERT_NE((void *)NULL, tls.dbg);
-        pthread_setspecific(dbgEGLThreadLocalStorageKey, &tls);
+        dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
+        ASSERT_NE((void *)NULL, dbg);
         for (unsigned int i = 0; i < sizeof(hooks) / sizeof(void *); i++)
             ((void **)&hooks)[i] = reinterpret_cast<void *>(glNoop);
     }
@@ -183,7 +177,7 @@
             return ret;
         }
     } caller;
-    const int contextId = reinterpret_cast<int>(tls.dbg);
+    const int contextId = reinterpret_cast<int>(dbg);
     glesv2debugger::Message msg, read;
 
     EXPECT_EQ(ret, MessageLoop(caller, msg, msg.glFinish));
@@ -214,25 +208,25 @@
 
 TEST_F(ServerFileContextTest, DisableEnableVertexAttribArray)
 {
-    Debug_glEnableVertexAttribArray(tls.dbg->MAX_VERTEX_ATTRIBS + 2); // should just ignore invalid index
+    Debug_glEnableVertexAttribArray(dbg->MAX_VERTEX_ATTRIBS + 2); // should just ignore invalid index
 
     glesv2debugger::Message read;
     rewind(file);
     Read(read);
     EXPECT_EQ(read.glEnableVertexAttribArray, read.function());
-    EXPECT_EQ(tls.dbg->MAX_VERTEX_ATTRIBS + 2, read.arg0());
+    EXPECT_EQ(dbg->MAX_VERTEX_ATTRIBS + 2, read.arg0());
     Read(read);
 
     rewind(file);
-    Debug_glDisableVertexAttribArray(tls.dbg->MAX_VERTEX_ATTRIBS + 4); // should just ignore invalid index
+    Debug_glDisableVertexAttribArray(dbg->MAX_VERTEX_ATTRIBS + 4); // should just ignore invalid index
     rewind(file);
     Read(read);
     Read(read);
 
-    for (unsigned int i = 0; i < tls.dbg->MAX_VERTEX_ATTRIBS; i += 5) {
+    for (unsigned int i = 0; i < dbg->MAX_VERTEX_ATTRIBS; i += 5) {
         rewind(file);
         Debug_glEnableVertexAttribArray(i);
-        EXPECT_TRUE(tls.dbg->vertexAttribs[i].enabled);
+        EXPECT_TRUE(dbg->vertexAttribs[i].enabled);
         rewind(file);
         Read(read);
         EXPECT_EQ(read.glEnableVertexAttribArray, read.function());
@@ -241,7 +235,7 @@
 
         rewind(file);
         Debug_glDisableVertexAttribArray(i);
-        EXPECT_FALSE(tls.dbg->vertexAttribs[i].enabled);
+        EXPECT_FALSE(dbg->vertexAttribs[i].enabled);
         rewind(file);
         Read(read);
         EXPECT_EQ(read.glDisableVertexAttribArray, read.function());
diff --git a/opengl/libs/GLES2_dbg/test/test_socket.cpp b/opengl/libs/GLES2_dbg/test/test_socket.cpp
index 617292e..b2148ac 100644
--- a/opengl/libs/GLES2_dbg/test/test_socket.cpp
+++ b/opengl/libs/GLES2_dbg/test/test_socket.cpp
@@ -19,13 +19,11 @@
 
 #include "header.h"
 #include "gtest/gtest.h"
-#include "egl_tls.h"
 #include "hooks.h"
 
 namespace android
 {
 extern int serverSock, clientSock;
-extern pthread_key_t dbgEGLThreadLocalStorageKey;
 };
 
 void * glNoop();
@@ -33,7 +31,7 @@
 class SocketContextTest : public ::testing::Test
 {
 protected:
-    tls_t tls;
+    DbgContext* dbg;
     gl_hooks_t hooks;
     int sock;
     char * buffer;
@@ -46,12 +44,8 @@
     }
 
     virtual void SetUp() {
-        if (dbgEGLThreadLocalStorageKey == -1)
-            pthread_key_create(&dbgEGLThreadLocalStorageKey, NULL);
-        ASSERT_NE(-1, dbgEGLThreadLocalStorageKey);
-        tls.dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
-        ASSERT_TRUE(tls.dbg != NULL);
-        pthread_setspecific(dbgEGLThreadLocalStorageKey, &tls);
+        dbg = new DbgContext(1, &hooks, 32, GL_RGBA, GL_UNSIGNED_BYTE);
+        ASSERT_TRUE(dbg != NULL);
         for (unsigned int i = 0; i < sizeof(hooks) / sizeof(void *); i++)
             ((void **)&hooks)[i] = (void *)glNoop;
 
@@ -73,7 +67,7 @@
     }
 
     void Write(glesv2debugger::Message & msg) const {
-        msg.set_context_id((int)tls.dbg);
+        msg.set_context_id((int)dbg);
         msg.set_type(msg.Response);
         ASSERT_TRUE(msg.has_context_id());
         ASSERT_TRUE(msg.has_function());
@@ -129,7 +123,7 @@
         }
     } caller;
     glesv2debugger::Message msg, read, cmd;
-    tls.dbg->expectResponse.Bit(msg.glFinish, true);
+    dbg->expectResponse.Bit(msg.glFinish, true);
 
     cmd.set_function(cmd.SKIP);
     cmd.set_expect_response(false);
@@ -158,7 +152,7 @@
         }
     } caller;
     glesv2debugger::Message msg, read, cmd;
-    tls.dbg->expectResponse.Bit(msg.glCreateShader, true);
+    dbg->expectResponse.Bit(msg.glCreateShader, true);
 
     cmd.set_function(cmd.CONTINUE);
     cmd.set_expect_response(false); // MessageLoop should automatically skip after continue
@@ -204,7 +198,7 @@
     glesv2debugger::Message msg, read, cmd;
     hooks.gl.glCreateShader = caller.CreateShader;
     hooks.gl.glCreateProgram = caller.CreateProgram;
-    tls.dbg->expectResponse.Bit(msg.glCreateProgram, true);
+    dbg->expectResponse.Bit(msg.glCreateProgram, true);
 
     cmd.set_function(cmd.glCreateShader);
     cmd.set_arg0(GL_FRAGMENT_SHADER);
@@ -272,7 +266,7 @@
     glesv2debugger::Message msg, read, cmd;
     hooks.gl.glCreateShader = caller.CreateShader;
     hooks.gl.glCreateProgram = caller.CreateProgram;
-    tls.dbg->expectResponse.Bit(msg.glCreateProgram, false);
+    dbg->expectResponse.Bit(msg.glCreateProgram, false);
 
     cmd.set_function(cmd.SETPROP);
     cmd.set_prop(cmd.ExpectResponse);
@@ -305,8 +299,8 @@
 
     EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateProgram));
 
-    EXPECT_TRUE(tls.dbg->expectResponse.Bit(msg.glCreateProgram));
-    EXPECT_EQ(819, tls.dbg->captureDraw);
+    EXPECT_TRUE(dbg->expectResponse.Bit(msg.glCreateProgram));
+    EXPECT_EQ(819, dbg->captureDraw);
 
     Read(read);
     EXPECT_EQ(read.glCreateProgram, read.function());
@@ -362,7 +356,7 @@
     } caller;
     glesv2debugger::Message msg, read, cmd;
     hooks.gl.glTexImage2D = caller.TexImage2D;
-    tls.dbg->expectResponse.Bit(msg.glTexImage2D, false);
+    dbg->expectResponse.Bit(msg.glTexImage2D, false);
 
     Debug_glTexImage2D(_target, _level, _internalformat, _width, _height, _border,
                        _format, _type, _pixels);
@@ -382,7 +376,7 @@
 
     EXPECT_TRUE(read.has_data());
     uint32_t dataLen = 0;
-    const unsigned char * data = tls.dbg->Decompress(read.data().data(),
+    const unsigned char * data = dbg->Decompress(read.data().data(),
                                  read.data().length(), &dataLen);
     EXPECT_EQ(sizeof(_pixels), dataLen);
     if (sizeof(_pixels) == dataLen)
@@ -435,7 +429,7 @@
     glesv2debugger::Message msg, read, cmd;
     hooks.gl.glCopyTexImage2D = caller.CopyTexImage2D;
     hooks.gl.glReadPixels = caller.ReadPixels;
-    tls.dbg->expectResponse.Bit(msg.glCopyTexImage2D, false);
+    dbg->expectResponse.Bit(msg.glCopyTexImage2D, false);
 
     Debug_glCopyTexImage2D(_target, _level, _internalformat, _x, _y, _width, _height,
                            _border);
@@ -459,7 +453,7 @@
     EXPECT_EQ(GL_RGBA, read.pixel_format());
     EXPECT_EQ(GL_UNSIGNED_BYTE, read.pixel_type());
     uint32_t dataLen = 0;
-    unsigned char * const data = tls.dbg->Decompress(read.data().data(),
+    unsigned char * const data = dbg->Decompress(read.data().data(),
                                  read.data().length(), &dataLen);
     ASSERT_EQ(sizeof(_pixels), dataLen);
     for (unsigned i = 0; i < sizeof(_pixels) / sizeof(*_pixels); i++)
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index c8f529a..d24b047 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -25,6 +25,9 @@
 
 #include "hooks.h"
 
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 4
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -41,6 +44,8 @@
 
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
 
+extern egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/egl_tls.h b/opengl/libs/egl_tls.h
deleted file mode 100644
index 087989a..0000000
--- a/opengl/libs/egl_tls.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- ** Copyright 2011, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- **     http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#ifndef ANDROID_EGL_TLS_H
-#define ANDROID_EGL_TLS_H
-
-#include <EGL/egl.h>
-
-#include "glesv2dbg.h"
-
-namespace android
-{
-struct tls_t {
-    tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE), dbg(0) { }
-    ~tls_t() {
-        if (dbg)
-            DestroyDbgContext(dbg);
-    }
-
-    EGLint      error;
-    EGLContext  ctx;
-    EGLBoolean  logCallWithNoContext;
-    DbgContext* dbg;
-};
-}
-
-#endif
diff --git a/opengl/libs/glesv2dbg.h b/opengl/libs/glesv2dbg.h
index ee2c011..44bc288 100644
--- a/opengl/libs/glesv2dbg.h
+++ b/opengl/libs/glesv2dbg.h
@@ -23,10 +23,9 @@
 {
 struct DbgContext;
 
-DbgContext * CreateDbgContext(const pthread_key_t EGLThreadLocalStorageKey,
-                              const unsigned version, const gl_hooks_t * const hooks);
+DbgContext* CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks);
 
-void DestroyDbgContext(DbgContext * const dbg);
+void dbgReleaseThread();
 
 // create and bind socket if haven't already, if failed to create socket or
 //  forceUseFile, then open /data/local/tmp/dump.gles2dbg, exit when size reached
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 03afc82..e5abeac 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -230,7 +230,7 @@
     boolean mSafeMode;
     WindowState mStatusBar = null;
     boolean mStatusBarCanHide;
-    int mScreenMarginBottom;
+    int mStatusBarHeight;
     final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
     WindowState mNavigationBar = null;
 
@@ -1071,12 +1071,20 @@
         return STATUS_BAR_LAYER;
     }
 
-    public int getNonDecorDisplayWidth(int fullWidth) {
+    public int getNonDecorDisplayWidth(int rotation, int fullWidth) {
         return fullWidth;
     }
 
-    public int getNonDecorDisplayHeight(int fullHeight) {
-        return fullHeight - mScreenMarginBottom;
+    public int getNonDecorDisplayHeight(int rotation, int fullHeight) {
+        return mStatusBarCanHide ? fullHeight : (fullHeight - mStatusBarHeight);
+    }
+
+    public int getConfigDisplayWidth(int rotation, int fullWidth) {
+        return fullWidth;
+    }
+
+    public int getConfigDisplayHeight(int rotation, int fullHeight) {
+        return fullHeight - mStatusBarHeight;
     }
 
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
@@ -1228,8 +1236,8 @@
                 // The Configuration will be stable by now, so we can load this
                 mStatusBarCanHide = mContext.getResources().getBoolean(
                         com.android.internal.R.bool.config_statusBarCanHide);
-                mScreenMarginBottom = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.screen_margin_bottom);
+                mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.status_bar_height);
 
                 break;
             case TYPE_NAVIGATION_BAR:
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 7028772..c365af5 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1371,31 +1371,70 @@
         }
     }
 
+    @Override
     public boolean switchToLastInputMethod(IBinder token) {
         synchronized (mMethodMap) {
             final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
-            if (lastIme == null) return false;
-            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
-            if (lastImi == null) return false;
-
-            final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
-            final int lastSubtypeHash = Integer.valueOf(lastIme.second);
-            // If the last IME is the same as the current IME and the last subtype is not defined,
-            // there is no need to switch to the last IME.
-            if (imiIdIsSame && lastSubtypeHash == NOT_A_SUBTYPE_ID) return false;
-
-            int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
-                    : mCurrentSubtype.hashCode();
-            if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second + ", from: "
-                            + mCurMethodId + ", " + currentSubtypeHash);
-                }
-                setInputMethodWithSubtypeId(token, lastIme.first, getSubtypeIdFromHashCode(
-                        lastImi, lastSubtypeHash));
-                return true;
+            final InputMethodInfo lastImi;
+            if (lastIme != null) {
+                lastImi = mMethodMap.get(lastIme.first);
+            } else {
+                lastImi = null;
             }
-            return false;
+            String targetLastImiId = null;
+            int subtypeId = NOT_A_SUBTYPE_ID;
+            if (lastIme != null && lastImi != null) {
+                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
+                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
+                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
+                        : mCurrentSubtype.hashCode();
+                // If the last IME is the same as the current IME and the last subtype is not
+                // defined, there is no need to switch to the last IME.
+                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
+                    targetLastImiId = lastIme.first;
+                    subtypeId = getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
+                }
+            }
+
+            if (TextUtils.isEmpty(targetLastImiId) && !canAddToLastInputMethod(mCurrentSubtype)) {
+                // This is a safety net. If the currentSubtype can't be added to the history
+                // and the framework couldn't find the last ime, we will make the last ime be
+                // the most applicable enabled keyboard subtype of the system imes.
+                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
+                if (enabled != null) {
+                    final int N = enabled.size();
+                    final String locale = mCurrentSubtype == null
+                            ? mRes.getConfiguration().locale.toString()
+                            : mCurrentSubtype.getLocale();
+                    for (int i = 0; i < N; ++i) {
+                        final InputMethodInfo imi = enabled.get(i);
+                        if (imi.getSubtypeCount() > 0 && isSystemIme(imi)) {
+                            InputMethodSubtype keyboardSubtype =
+                                    findLastResortApplicableSubtypeLocked(mRes, getSubtypes(imi),
+                                            SUBTYPE_MODE_KEYBOARD, locale, true);
+                            if (keyboardSubtype != null) {
+                                targetLastImiId = imi.getId();
+                                subtypeId = getSubtypeIdFromHashCode(
+                                        imi, keyboardSubtype.hashCode());
+                                if(keyboardSubtype.getLocale().equals(locale)) {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (!TextUtils.isEmpty(targetLastImiId)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
+                            + ", from: " + mCurMethodId + ", " + subtypeId);
+                }
+                setInputMethodWithSubtypeId(token, targetLastImiId, subtypeId);
+                return true;
+            } else {
+                return false;
+            }
         }
     }
 
@@ -2619,7 +2658,7 @@
             List<Pair<String, ArrayList<String>>> enabledImes =
                     getEnabledInputMethodsAndSubtypeListLocked();
             List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistoryLocked();
-            for (Pair<String, String> imeAndSubtype: subtypeHistory) {
+            for (Pair<String, String> imeAndSubtype : subtypeHistory) {
                 final String imeInTheHistory = imeAndSubtype.first;
                 // If imeId is empty, returns the first IME and subtype in the history
                 if (TextUtils.isEmpty(imeId) || imeInTheHistory.equals(imeId)) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index a2d10df..41ec63a 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -568,31 +568,10 @@
      * @param wifiConfig SSID, security and channel details as
      *        part of WifiConfiguration
      * @param enabled true to enable and false to disable
-     * @return {@code true} if the start operation was
-     *         started or is already in the queue.
      */
-    public synchronized boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
+    public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         enforceChangePermission();
-
-        if (enabled) {
-            /* Use default config if there is no existing config */
-            if (wifiConfig == null && ((wifiConfig = getWifiApConfiguration()) == null)) {
-                wifiConfig = new WifiConfiguration();
-                wifiConfig.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
-                wifiConfig.allowedKeyManagement.set(KeyMgmt.NONE);
-            }
-            /*
-             * Caller might not have WRITE_SECURE_SETTINGS,
-             * only CHANGE_WIFI_STATE is enforced
-             */
-            long ident = Binder.clearCallingIdentity();
-            setWifiApConfiguration(wifiConfig);
-            Binder.restoreCallingIdentity(ident);
-        }
-
         mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);
-
-        return true;
     }
 
     /**
@@ -612,38 +591,20 @@
      * see {@link WifiManager#getWifiApConfiguration()}
      * @return soft access point configuration
      */
-    public synchronized WifiConfiguration getWifiApConfiguration() {
-        final ContentResolver cr = mContext.getContentResolver();
-        WifiConfiguration wifiConfig = new WifiConfiguration();
-        int authType;
-        try {
-            wifiConfig.SSID = Settings.Secure.getString(cr, Settings.Secure.WIFI_AP_SSID);
-            if (wifiConfig.SSID == null)
-                return null;
-            authType = Settings.Secure.getInt(cr, Settings.Secure.WIFI_AP_SECURITY);
-            wifiConfig.allowedKeyManagement.set(authType);
-            wifiConfig.preSharedKey = Settings.Secure.getString(cr, Settings.Secure.WIFI_AP_PASSWD);
-            return wifiConfig;
-        } catch (Settings.SettingNotFoundException e) {
-            Slog.e(TAG,"AP settings not found, returning");
-            return null;
-        }
+    public WifiConfiguration getWifiApConfiguration() {
+        enforceAccessPermission();
+        return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel);
     }
 
     /**
      * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)}
      * @param wifiConfig WifiConfiguration details for soft access point
      */
-    public synchronized void setWifiApConfiguration(WifiConfiguration wifiConfig) {
+    public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
         enforceChangePermission();
-        final ContentResolver cr = mContext.getContentResolver();
         if (wifiConfig == null)
             return;
-        int authType = wifiConfig.getAuthType();
-        Settings.Secure.putString(cr, Settings.Secure.WIFI_AP_SSID, wifiConfig.SSID);
-        Settings.Secure.putInt(cr, Settings.Secure.WIFI_AP_SECURITY, authType);
-        if (authType != KeyMgmt.NONE)
-            Settings.Secure.putString(cr, Settings.Secure.WIFI_AP_PASSWD, wifiConfig.preSharedKey);
+        mWifiStateMachine.setWifiApConfiguration(wifiConfig);
     }
 
     /**
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index fb97089..4c7f595 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -110,9 +110,6 @@
     // Temporary array for storing pointer IDs.
     private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
 
-    // Temporary array for mapping new to old pointer IDs while filtering inactive pointers.
-    private final int [] mTempNewToOldPointerIndexMap = new int[MAX_POINTER_COUNT];
-
     // Temporary array for storing PointerProperties
     private final PointerProperties[] mTempPointerProperties =
             PointerProperties.createArray(MAX_POINTER_COUNT);
@@ -229,7 +226,7 @@
                 // Send a hover for every finger down so the user gets feedback
                 // where she is currently touching.
                 mSendHoverDelayed.forceSendAndRemove();
-                mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, 0, policyFlags,
+                mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, 1, policyFlags,
                         DELAY_SEND_HOVER_MOVE);
             } break;
             case MotionEvent.ACTION_POINTER_DOWN: {
@@ -243,13 +240,13 @@
                         // accessibility event from the hovered view.
                         mSendHoverDelayed.remove();
                         final int pointerId = pointerTracker.getPrimaryActivePointerId();
-                        final int pointerIndex = event.findPointerIndex(pointerId);
+                        final int pointerIdBits = (1 << pointerId);
                         final int lastAction = pointerTracker.getLastInjectedHoverAction();
                         // If a schedules hover enter for another pointer is delivered we send move.
                         final int action = (lastAction == MotionEvent.ACTION_HOVER_ENTER)
                                 ? MotionEvent.ACTION_HOVER_MOVE
                                 : MotionEvent.ACTION_HOVER_ENTER;
-                        mSendHoverDelayed.post(event, action, pointerIndex, policyFlags,
+                        mSendHoverDelayed.post(event, action, pointerIdBits, policyFlags,
                                 DELAY_SEND_HOVER_MOVE);
 
                         if (mLastTouchExploreEvent == null) {
@@ -268,14 +265,14 @@
                 }
             } break;
             case MotionEvent.ACTION_MOVE: {
+                final int pointerId = pointerTracker.getPrimaryActivePointerId();
+                final int pointerIndex = event.findPointerIndex(pointerId);
+                final int pointerIdBits = (1 << pointerId);
                 switch (activePointerCount) {
                     case 0: {
                         /* do nothing - no active pointers so we swallow the event */
                     } break;
                     case 1: {
-                        final int pointerId = pointerTracker.getPrimaryActivePointerId();
-                        final int pointerIndex = event.findPointerIndex(pointerId);
-
                         // Detect touch exploration gesture start by having one active pointer
                         // that moved more than a given distance.
                         if (!mTouchExploreGestureInProgress) {
@@ -290,12 +287,19 @@
                                 sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
                                 // Make sure the scheduled down/move event is sent.
                                 mSendHoverDelayed.forceSendAndRemove();
-                                sendHoverEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIndex,
+                                // If we have transitioned to exploring state from another one
+                                // we need to send a hover enter event here.
+                                final int lastAction = mPointerTracker.getLastInjectedHoverAction();
+                                if (lastAction == MotionEvent.ACTION_HOVER_EXIT) {
+                                    sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER,
+                                            pointerIdBits, policyFlags);
+                                }
+                                sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits,
                                         policyFlags);
                             }
                         } else {
                             // Touch exploration gesture in progress so send a hover event.
-                            sendHoverEvent(event,  MotionEvent.ACTION_HOVER_MOVE, pointerIndex,
+                            sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits,
                                     policyFlags);
                         }
 
@@ -337,13 +341,10 @@
                         }
                     } break;
                     case 2: {
-                        // Make sure the scheduled hover enter is delivered.
                         mSendHoverDelayed.forceSendAndRemove();
                         // We want to no longer hover over the location so subsequent
                         // touch at the same spot will generate a hover enter.
-                        final int pointerId = pointerTracker.getPrimaryActivePointerId();
-                        final int pointerIndex = event.findPointerIndex(pointerId);
-                        sendHoverEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIndex,
+                        sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
                                 policyFlags);
 
                         if (isDraggingGesture(event)) {
@@ -354,8 +355,9 @@
                                 sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
                                 mTouchExploreGestureInProgress = false;
                             }
-                            mDraggingPointerId = pointerTracker.getPrimaryActivePointerId();
-                            sendDragEvent(event, MotionEvent.ACTION_DOWN, policyFlags);
+                            mDraggingPointerId = pointerId;
+                            sendMotionEvent(event, MotionEvent.ACTION_DOWN, pointerIdBits,
+                                    policyFlags);
                         } else {
                             // Two pointers moving arbitrary are delegated to the view hierarchy.
                             mCurrentState = STATE_DELEGATING;
@@ -367,13 +369,10 @@
                         }
                     } break;
                     default: {
-                        // Make sure the scheduled hover enter is delivered.
                         mSendHoverDelayed.forceSendAndRemove();
                         // We want to no longer hover over the location so subsequent
                         // touch at the same spot will generate a hover enter.
-                        final int pointerId = pointerTracker.getPrimaryActivePointerId();
-                        final int pointerIndex = event.findPointerIndex(pointerId);
-                        sendHoverEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIndex,
+                        sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
                                 policyFlags);
 
                         // More than two pointers are delegated to the view hierarchy.
@@ -389,6 +388,8 @@
             } break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_POINTER_UP: {
+                final int pointerId = pointerTracker.getLastReceivedUpPointerId();
+                final int pointerIdBits = (1 << pointerId);
                 switch (activePointerCount) {
                     case 0: {
                         // If the pointer that went up was not active we have nothing to do.
@@ -404,7 +405,6 @@
 
                         // Detect whether to activate i.e. click on the last explored location.
                         if (mLastTouchExploreEvent != null) {
-                            final int pointerId = pointerTracker.getLastReceivedUpPointerId();
 
                             // If the down was not in the time slop => nothing else to do.
                             final long eventTime =
@@ -413,7 +413,11 @@
                             final long deltaTime = eventTime - exploreTime;
                             if (deltaTime > ACTIVATION_TIME_SLOP) {
                                 mSendHoverDelayed.forceSendAndRemove();
-                                scheduleHoverExit(event, policyFlags);
+                                final int lastAction = mPointerTracker.getLastInjectedHoverAction();
+                                if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
+                                    sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
+                                            pointerIdBits, policyFlags);
+                                }
                                 mLastTouchExploreEvent = MotionEvent.obtain(event);
                                 break;
                             }
@@ -427,7 +431,11 @@
                             final float deltaMove = (float) Math.hypot(deltaX, deltaY);
                             if (deltaMove > mTouchExplorationTapSlop) {
                                 mSendHoverDelayed.forceSendAndRemove();
-                                scheduleHoverExit(event, policyFlags);
+                                final int lastAction = mPointerTracker.getLastInjectedHoverAction();
+                                if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
+                                    sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
+                                            pointerIdBits, policyFlags);
+                                }
                                 mLastTouchExploreEvent = MotionEvent.obtain(event);
                                 break;
                             }
@@ -438,7 +446,11 @@
                             mLastTouchExploreEvent = null;
                         } else {
                             mSendHoverDelayed.forceSendAndRemove();
-                            scheduleHoverExit(event, policyFlags);
+                            final int lastAction = mPointerTracker.getLastInjectedHoverAction();
+                            if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
+                                sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
+                                        pointerIdBits, policyFlags);
+                            }
                             mLastTouchExploreEvent = MotionEvent.obtain(event);
                         }
                     } break;
@@ -448,8 +460,8 @@
                 final int lastAction = pointerTracker.getLastInjectedHoverAction();
                 if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
                     final int pointerId = pointerTracker.getPrimaryActivePointerId();
-                    final int pointerIndex = event.findPointerIndex(pointerId);
-                    sendHoverEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIndex,
+                    final int pointerIdBits = (1 << pointerId);
+                    sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
                             policyFlags);
                 }
                 clear();
@@ -464,6 +476,7 @@
      * @param policyFlags The policy flags associated with the event.
      */
     private void handleMotionEventStateDragging(MotionEvent event, int policyFlags) {
+        final int pointerIdBits = (1 << mDraggingPointerId);
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 throw new IllegalStateException("Dragging state can be reached only if two "
@@ -473,7 +486,7 @@
                 // We are in dragging state so we have two pointers and another one
                 // goes down => delegate the three pointers to the view hierarchy
                 mCurrentState = STATE_DELEGATING;
-                sendDragEvent(event, MotionEvent.ACTION_UP, policyFlags);
+                sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
                 sendDownForAllActiveNotInjectedPointers(event, policyFlags);
             } break;
             case MotionEvent.ACTION_MOVE: {
@@ -482,13 +495,15 @@
                     case 2: {
                         if (isDraggingGesture(event)) {
                             // If still dragging send a drag event.
-                            sendDragEvent(event, MotionEvent.ACTION_MOVE, policyFlags);
+                            sendMotionEvent(event, MotionEvent.ACTION_MOVE, pointerIdBits,
+                                    policyFlags);
                         } else {
                             // The two pointers are moving either in different directions or
                             // no close enough => delegate the gesture to the view hierarchy.
                             mCurrentState = STATE_DELEGATING;
                             // Send an event to the end of the drag gesture.
-                            sendDragEvent(event, MotionEvent.ACTION_UP, policyFlags);
+                            sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
+                                    policyFlags);
                             // Deliver all active pointers to the view hierarchy.
                             sendDownForAllActiveNotInjectedPointers(event, policyFlags);
                         }
@@ -496,7 +511,8 @@
                     default: {
                         mCurrentState = STATE_DELEGATING;
                         // Send an event to the end of the drag gesture.
-                        sendDragEvent(event, MotionEvent.ACTION_UP, policyFlags);
+                        sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
+                                policyFlags);
                         // Deliver all active pointers to the view hierarchy.
                         sendDownForAllActiveNotInjectedPointers(event, policyFlags);
                     }
@@ -505,7 +521,7 @@
             case MotionEvent.ACTION_POINTER_UP: {
                 mCurrentState = STATE_TOUCH_EXPLORING;
                 // Send an event to the end of the drag gesture.
-                sendDragEvent(event, MotionEvent.ACTION_UP, policyFlags);
+                sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
              } break;
             case MotionEvent.ACTION_CANCEL: {
                 clear();
@@ -551,23 +567,6 @@
     }
 
     /**
-     * Schedules a hover up event so subsequent poking on the same location after
-     * the scheduled delay will perform exploration.
-     *
-     * @param prototype The prototype from which to create the injected events.
-     * @param policyFlags The policy flags associated with the event.
-     */
-    private void scheduleHoverExit(MotionEvent prototype,
-            int policyFlags) {
-        final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
-        final int pointerIndex = prototype.findPointerIndex(pointerId);
-        // We want to no longer hover over the location so subsequent
-        // touch at the same spot will generate a hover enter.
-        mSendHoverDelayed.post(prototype, MotionEvent.ACTION_HOVER_EXIT,
-                 pointerIndex, policyFlags, ACTIVATION_TIME_SLOP);
-    }
-
-    /**
      * Sends down events to the view hierarchy for all active pointers which are
      * not already being delivered i.e. pointers that are not yet injected.
      *
@@ -600,9 +599,9 @@
             final long downTime = pointerTracker.getLastInjectedDownEventTime();
             final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, pointerDataIndex);
             final int pointerCount = pointerDataIndex + 1;
-            final long pointerDownTime = SystemClock.uptimeMillis();
+            final long eventTime = SystemClock.uptimeMillis();
 
-            MotionEvent event = MotionEvent.obtain(downTime, pointerDownTime,
+            MotionEvent event = MotionEvent.obtain(downTime, eventTime,
                     action, pointerCount, pointerProperties, pointerCoords,
                     prototype.getMetaState(), prototype.getButtonState(),
                     prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
@@ -680,89 +679,18 @@
             return;
         }
 
-        // Filter out inactive pointers from the event and inject it.
-        final PointerProperties[] pointerProperties = mTempPointerProperties;
-        final PointerCoords[] pointerCoords = mTempPointerCoords;
-        int [] newToOldPointerIndexMap = mTempNewToOldPointerIndexMap;
-        int newPointerIndex = 0;
-        int actionIndex = prototype.getActionIndex();
-
-        final int oldPointerCount = prototype.getPointerCount();
-        for (int oldPointerIndex = 0; oldPointerIndex < oldPointerCount; oldPointerIndex++) {
-            final int pointerId = prototype.getPointerId(oldPointerIndex);
-
+        int pointerIdBits = 0;
+        final int pointerCount = prototype.getPointerCount();
+        for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
+            final int pointerId = prototype.getPointerId(pointerIndex);
             // If the pointer is inactive or the pointer that just went up
             // was inactive we strip the pointer data from the event.
-            if (!pointerTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
-                if (oldPointerIndex <= prototype.getActionIndex()) {
-                    actionIndex--;
-                }
-                continue;
+            if (pointerTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
+                pointerIdBits |= (1 << pointerId);
             }
-
-            newToOldPointerIndexMap[newPointerIndex] = oldPointerIndex;
-            prototype.getPointerProperties(oldPointerIndex, pointerProperties[newPointerIndex]);
-            prototype.getPointerCoords(oldPointerIndex, pointerCoords[newPointerIndex]);
-
-            newPointerIndex++;
         }
 
-        // If we skipped all pointers => nothing to do.
-        if (newPointerIndex == 0) {
-            return;
-        }
-
-        // Populate and inject the event.
-        final long downTime = pointerTracker.getLastInjectedDownEventTime();
-        final int action = computeInjectionAction(prototype.getActionMasked(), actionIndex);
-        final int newPointerCount = newPointerIndex;
-        MotionEvent prunedEvent = MotionEvent.obtain(downTime, prototype.getEventTime(), action,
-                newPointerCount, pointerProperties, pointerCoords,
-                prototype.getMetaState(), prototype.getButtonState(),
-                prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
-                prototype.getEdgeFlags(), prototype.getSource(),prototype.getFlags());
-
-        // Add the filtered history.
-        final int historySize = prototype.getHistorySize();
-        for (int historyIndex = 0; historyIndex < historySize; historyIndex++) {
-            for (int pointerIndex = 0; pointerIndex < newPointerCount; pointerIndex++) {
-                final int oldPointerIndex = newToOldPointerIndexMap[pointerIndex];
-                prototype.getPointerCoords(oldPointerIndex, pointerCoords[pointerIndex]);
-            }
-            final long historicalTime = prototype.getHistoricalEventTime(historyIndex);
-            prunedEvent.addBatch(historicalTime, pointerCoords, 0);
-        }
-
-        sendMotionEvent(prunedEvent, policyFlags);
-        prunedEvent.recycle();
-    }
-
-    /**
-     * Sends a dragging event from a two pointer event. The two pointers are
-     * merged into one and delivered to the view hierarchy. Through the entire
-     * drag gesture the pointer id delivered to the view hierarchy is the same.
-     *
-     * @param prototype The prototype from which to create the injected event.
-     * @param action The dragging action that is to be injected.
-     * @param policyFlags The policy flags associated with the event.
-     */
-    private void sendDragEvent(MotionEvent prototype, int action, int policyFlags) {
-        final PointerProperties[] pointerProperties = mTempPointerProperties;
-        final PointerCoords[] pointerCoords = mTempPointerCoords;
-        final int pointerId = mDraggingPointerId;
-        final int pointerIndex = prototype.findPointerIndex(pointerId);
-
-        // Populate the event with the date of the dragging pointer and inject it.
-        prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
-        prototype.getPointerCoords(pointerIndex, pointerCoords[0]);
-
-        MotionEvent event = MotionEvent.obtain(prototype.getDownTime(),
-                prototype.getEventTime(), action, 1, pointerProperties, pointerCoords,
-                prototype.getMetaState(), prototype.getButtonState(),
-                prototype.getXPrecision(), prototype.getYPrecision(),
-                prototype.getDeviceId(), prototype.getEdgeFlags(), prototype.getSource(),
-                prototype.getFlags());
-
+        MotionEvent event = prototype.split(pointerIdBits);
         sendMotionEvent(event, policyFlags);
         event.recycle();
     }
@@ -798,32 +726,20 @@
     }
 
     /**
-     * Sends a hover event.
+     * Sends an event.
      *
-     * @param prototype The prototype from which to create the injected event.
-     * @param action The hover action.
-     * @param pointerIndex The action pointer index.
+     * @param event The event to send.
+     * @param action The action of the event.
+     * @param pointerIdBits The bits of the pointers to send.
      * @param policyFlags The policy flags associated with the event.
      */
-    private void sendHoverEvent(MotionEvent prototype, int action, int pointerIndex, int
-            policyFlags) {
-        final PointerProperties[] pointerProperties = mTempPointerProperties;
-        final PointerCoords[] pointerCoords = mTempPointerCoords;
-
-        prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
-        prototype.getPointerCoords(pointerIndex, pointerCoords[0]);
-
-        final long downTime = mPointerTracker.getLastInjectedDownEventTime();
-
-        // Populate and inject a hover event.
-        MotionEvent hoverEvent = MotionEvent.obtain(downTime, prototype.getEventTime(), action,
-                1, pointerProperties, pointerCoords,
-                prototype.getMetaState(), prototype.getButtonState(),
-                prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
-                prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
-
-        sendMotionEvent(hoverEvent, policyFlags);
-        hoverEvent.recycle();
+    private void sendMotionEvent(MotionEvent prototype, int action, int pointerIdBits,
+            int policyFlags) {
+        MotionEvent event = prototype.split(pointerIdBits);
+        event.setDownTime(mPointerTracker.getLastInjectedDownEventTime());
+        event.setAction(action);
+        sendMotionEvent(event, policyFlags);
+        event.recycle();
     }
 
     /**
@@ -1381,6 +1297,9 @@
             final int pointerId = event.getPointerId(pointerIndex);
             final int pointerFlag = (1 << pointerId);
             mInjectedPointersDown &= ~pointerFlag;
+            if (mInjectedPointersDown == 0) {
+                mLastInjectedDownEventTime = 0;
+            }
         }
 
         /**
@@ -1481,15 +1400,15 @@
 
         private MotionEvent mEvent;
         private int mAction;
-        private int mPointerIndex;
+        private int mPointerIdBits;
         private int mPolicyFlags;
 
-        public void post(MotionEvent prototype, int action, int pointerIndex, int policyFlags,
+        public void post(MotionEvent prototype, int action, int pointerIdBits, int policyFlags,
                 long delay) {
             remove();
             mEvent = MotionEvent.obtain(prototype);
             mAction = action;
-            mPointerIndex = pointerIndex;
+            mPointerIdBits = pointerIdBits;
             mPolicyFlags = policyFlags;
             mHandler.postDelayed(this, delay);
         }
@@ -1510,7 +1429,7 @@
             mEvent.recycle();
             mEvent = null;
             mAction = 0;
-            mPointerIndex = -1;
+            mPointerIdBits = -1;
             mPolicyFlags = 0;
         }
 
@@ -1532,7 +1451,7 @@
                 }
             }
 
-            sendHoverEvent(mEvent, mAction, mPointerIndex, mPolicyFlags);
+            sendMotionEvent(mEvent, mAction, mPointerIdBits, mPolicyFlags);
             clear();
         }
     }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index de439ca..e1fbe1c 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -59,6 +59,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageStats;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
@@ -2371,63 +2372,112 @@
         }
     }
 
-    public List<PackageInfo> getInstalledPackages(int flags) {
-        final ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
+    private static final int getContinuationPoint(final String[] keys, final String key) {
+        final int index;
+        if (key == null) {
+            index = 0;
+        } else {
+            final int insertPoint = Arrays.binarySearch(keys, key);
+            if (insertPoint < 0) {
+                index = -insertPoint;
+            } else {
+                index = insertPoint + 1;
+            }
+        }
+        return index;
+    }
+
+    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) {
+        final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
+        final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+        final String[] keys;
 
         // writer
         synchronized (mPackages) {
-            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
-                final Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
-                while (i.hasNext()) {
-                    final PackageSetting ps = i.next();
-                    final PackageInfo psPkg = generatePackageInfoFromSettingsLPw(ps.name, flags);
-                    if (psPkg != null) {
-                        finalList.add(psPkg);
+            if (listUninstalled) {
+                keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
+            } else {
+                keys = mPackages.keySet().toArray(new String[mPackages.size()]);
+            }
+
+            Arrays.sort(keys);
+            int i = getContinuationPoint(keys, lastRead);
+            final int N = keys.length;
+
+            while (i < N) {
+                final String packageName = keys[i++];
+
+                PackageInfo pi = null;
+                if (listUninstalled) {
+                    final PackageSetting ps = mSettings.mPackages.get(packageName);
+                    if (ps != null) {
+                        pi = generatePackageInfoFromSettingsLPw(ps.name, flags);
+                    }
+                } else {
+                    final PackageParser.Package p = mPackages.get(packageName);
+                    if (p != null) {
+                        pi = generatePackageInfo(p, flags);
                     }
                 }
-            } else {
-                final Iterator<PackageParser.Package> i = mPackages.values().iterator();
-                while (i.hasNext()) {
-                    final PackageParser.Package p = i.next();
-                    if (p.applicationInfo != null) {
-                        final PackageInfo pi = generatePackageInfo(p, flags);
-                        if (pi != null) {
-                            finalList.add(pi);
-                        }
-                    }
+
+                if (pi != null && !list.append(pi)) {
+                    break;
                 }
             }
+
+            if (i == N) {
+                list.setLastSlice(true);
+            }
         }
-        return finalList;
+
+        return list;
     }
 
-    public List<ApplicationInfo> getInstalledApplications(int flags) {
-        final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
+    public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
+            String lastRead) {
+        final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
+        final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+        final String[] keys;
+
         // writer
-        synchronized(mPackages) {
-            if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
-                final Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
-                while (i.hasNext()) {
-                    final PackageSetting ps = i.next();
-                    ApplicationInfo ai = generateApplicationInfoFromSettingsLPw(ps.name, flags);
-                    if(ai != null) {
-                        finalList.add(ai);
+        synchronized (mPackages) {
+            if (listUninstalled) {
+                keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
+            } else {
+                keys = mPackages.keySet().toArray(new String[mPackages.size()]);
+            }
+
+            Arrays.sort(keys);
+            int i = getContinuationPoint(keys, lastRead);
+            final int N = keys.length;
+
+            while (i < N) {
+                final String packageName = keys[i++];
+
+                ApplicationInfo ai = null;
+                if (listUninstalled) {
+                    final PackageSetting ps = mSettings.mPackages.get(packageName);
+                    if (ps != null) {
+                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags);
+                    }
+                } else {
+                    final PackageParser.Package p = mPackages.get(packageName);
+                    if (p != null) {
+                        ai = PackageParser.generateApplicationInfo(p, flags);
                     }
                 }
-            } else {
-                final Iterator<PackageParser.Package> i = mPackages.values().iterator();
-                while (i.hasNext()) {
-                    final PackageParser.Package p = i.next();
-                    if (p.applicationInfo != null) {
-                        ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
-                        if(ai != null) {
-                            finalList.add(ai);
-                        }
-                    }
+
+                if (ai != null && !list.append(ai)) {
+                    break;
                 }
             }
+
+            if (i == N) {
+                list.setLastSlice(true);
+            }
         }
-        return finalList;
+
+        return list;
     }
 
     public List<ApplicationInfo> getPersistentApplications(int flags) {
@@ -8052,7 +8102,8 @@
     }
 
     public UserInfo createUser(String name, int flags) {
-        UserInfo userInfo = mUserManager.createUser(name, flags, getInstalledApplications(0));
+        // TODO(kroot): fix this API
+        UserInfo userInfo = mUserManager.createUser(name, flags, new ArrayList<ApplicationInfo>());
         return userInfo;
     }
 
diff --git a/services/java/com/android/server/wm/ViewServer.java b/services/java/com/android/server/wm/ViewServer.java
index 9fb35b96..70cb26a 100644
--- a/services/java/com/android/server/wm/ViewServer.java
+++ b/services/java/com/android/server/wm/ViewServer.java
@@ -73,19 +73,6 @@
     private ExecutorService mThreadPool;
 
     /**
-     * Creates a new ViewServer associated with the specified window manager.
-     * The server uses the default port {@link #VIEW_SERVER_DEFAULT_PORT}. The server
-     * is not started by default.
-     *
-     * @param windowManager The window manager used to communicate with the views.
-     *
-     * @see #start()
-     */
-    ViewServer(WindowManagerService windowManager) {
-        this(windowManager, VIEW_SERVER_DEFAULT_PORT);
-    }
-
-    /**
      * Creates a new ViewServer associated with the specified window manager on the
      * specified local port. The server is not started by default.
      *
@@ -177,7 +164,7 @@
             // Any uncaught exception will crash the system process
             try {
                 Socket client = mServer.accept();
-                if(mThreadPool != null) {
+                if (mThreadPool != null) {
                     mThreadPool.submit(new ViewServerWorker(client));
                 } else {
                     try {
@@ -220,6 +207,7 @@
         private Socket mClient;
         private boolean mNeedWindowListUpdate;
         private boolean mNeedFocusedWindowUpdate;
+
         public ViewServerWorker(Socket client) {
             mClient = client;
             mNeedWindowListUpdate = false;
@@ -255,7 +243,7 @@
                     result = mWindowManager.viewServerListWindows(mClient);
                 } else if (COMMAND_WINDOW_MANAGER_GET_FOCUS.equalsIgnoreCase(command)) {
                     result = mWindowManager.viewServerGetFocusedWindow(mClient);
-                } else if(COMMAND_WINDOW_MANAGER_AUTOLIST.equalsIgnoreCase(command)) {
+                } else if (COMMAND_WINDOW_MANAGER_AUTOLIST.equalsIgnoreCase(command)) {
                     result = windowManagerAutolistLoop();
                 } else {
                     result = mWindowManager.viewServerWindowCommand(mClient,
@@ -263,7 +251,7 @@
                 }
 
                 if (!result) {
-                    Slog.w(LOG_TAG, "An error occured with the command: " + command);
+                    Slog.w(LOG_TAG, "An error occurred with the command: " + command);
                 }
             } catch(IOException e) {
                 Slog.w(LOG_TAG, "Connection error: ", e);
@@ -321,11 +309,11 @@
                             needFocusedWindowUpdate = true;
                         }
                     }
-                    if(needWindowListUpdate) {
+                    if (needWindowListUpdate) {
                         out.write("LIST UPDATE\n");
                         out.flush();
                     }
-                    if(needFocusedWindowUpdate) {
+                    if (needFocusedWindowUpdate) {
                         out.write("FOCUS UPDATE\n");
                         out.flush();
                     }
@@ -337,6 +325,7 @@
                     try {
                         out.close();
                     } catch (IOException e) {
+                        // Ignore
                     }
                 }
                 mWindowManager.removeWindowChangeListener(this);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 9890bec..92c490e 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -4783,8 +4783,8 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mPolicy.getNonDecorDisplayWidth(mCurDisplayWidth);
-            dh = mPolicy.getNonDecorDisplayHeight(mCurDisplayHeight);
+            dw = mPolicy.getNonDecorDisplayWidth(mRotation, mCurDisplayWidth);
+            dh = mPolicy.getNonDecorDisplayHeight(mRotation, mCurDisplayHeight);
 
             int aboveAppLayer = mPolicy.windowTypeToLayerLw(
                     WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -5501,6 +5501,14 @@
         return config;
     }
 
+    private int reduceConfigWidthSize(int curSize, int rotation, float density, int dw) {
+        int size = (int)(mPolicy.getConfigDisplayWidth(rotation, dw) / density);
+        if (size < curSize) {
+            curSize = size;
+        }
+        return curSize;
+    }
+
     boolean computeNewConfigurationLocked(Configuration config) {
         if (mDisplay == null) {
             return false;
@@ -5551,14 +5559,37 @@
 
         // Override display width and height with what we are computing,
         // to be sure they remain consistent.
-        dm.widthPixels = dm.realWidthPixels = mPolicy.getNonDecorDisplayWidth(dw);
-        dm.heightPixels = dm.realHeightPixels = mPolicy.getNonDecorDisplayHeight(dh);
+        dm.widthPixels = dm.realWidthPixels = mPolicy.getNonDecorDisplayWidth(
+                mRotation, dw);
+        dm.heightPixels = dm.realHeightPixels = mPolicy.getNonDecorDisplayHeight(
+                mRotation, dh);
 
         mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame(
                 dm, mCompatibleScreenFrame, null);
 
-        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
-        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
+        config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(mRotation, dw) / dm.density);
+        config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(mRotation, dh) / dm.density);
+
+        // We need to determine the smallest width that will occur under normal
+        // operation.  To this, start with the base screen size and compute the
+        // width under the different possible rotations.  We need to un-rotate
+        // the current screen dimensions before doing this.
+        int unrotDw, unrotDh;
+        if (rotated) {
+            unrotDw = dh;
+            unrotDh = dw;
+        } else {
+            unrotDw = dw;
+            unrotDh = dh;
+        }
+        config.smallestScreenWidthDp = reduceConfigWidthSize(unrotDw,
+                Surface.ROTATION_0, dm.density, unrotDw);
+        config.smallestScreenWidthDp = reduceConfigWidthSize(config.smallestScreenWidthDp,
+                Surface.ROTATION_90, dm.density, unrotDh);
+        config.smallestScreenWidthDp = reduceConfigWidthSize(config.smallestScreenWidthDp,
+                Surface.ROTATION_180, dm.density, unrotDw);
+        config.smallestScreenWidthDp = reduceConfigWidthSize(config.smallestScreenWidthDp,
+                Surface.ROTATION_270, dm.density, unrotDh);
 
         // Compute the screen layout size class.
         int screenLayout;
@@ -6810,9 +6841,6 @@
         final int dw = mCurDisplayWidth;
         final int dh = mCurDisplayHeight;
 
-        final int innerDw = mPolicy.getNonDecorDisplayWidth(dw);
-        final int innerDh = mPolicy.getNonDecorDisplayHeight(dh);
-
         final int N = mWindows.size();
         int i;
 
@@ -6933,8 +6961,8 @@
         final int dw = mCurDisplayWidth;
         final int dh = mCurDisplayHeight;
 
-        final int innerDw = mPolicy.getNonDecorDisplayWidth(dw);
-        final int innerDh = mPolicy.getNonDecorDisplayHeight(dh);
+        final int innerDw = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
+        final int innerDh = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
 
         int i;
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index ce1ab3d..c5e69ff 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -44,8 +44,7 @@
 // ---------------------------------------------------------------------------
 
 SensorService::SensorService()
-    : Thread(false),
-      mDump("android.permission.DUMP"),
+    : mDump("android.permission.DUMP"),
       mInitCheck(NO_INIT)
 {
 }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2cabe02..8df2b92 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -79,6 +79,10 @@
     }
 }
 
+void Layer::destroy() const {
+    mFlinger->destroyLayer(this);
+}
+
 status_t Layer::setToken(const sp<UserClient>& userClient,
         SharedClient* sharedClient, int32_t token)
 {
@@ -147,18 +151,6 @@
     return sur;
 }
 
-status_t Layer::ditch()
-{
-    // NOTE: Called from the main UI thread
-
-    // the layer is not on screen anymore. free as much resources as possible
-    mFreezeLock.clear();
-
-    Mutex::Autolock _l(mLock);
-    mWidth = mHeight = 0;
-    return NO_ERROR;
-}
-
 status_t Layer::setBuffers( uint32_t w, uint32_t h,
                             PixelFormat format, uint32_t flags)
 {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 128f93d..278d64e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -82,7 +82,6 @@
     virtual bool isSecure() const           { return mSecure; }
     virtual bool isProtected() const;
     virtual sp<Surface> createSurface() const;
-    virtual status_t ditch();
     virtual void onRemoved();
 
     // only for debugging
@@ -93,6 +92,7 @@
         return mFreezeLock; }
 
 protected:
+    virtual void destroy() const;
     virtual void dump(String8& result, char* scratch, size_t size) const;
 
 private:
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 6025ed4..022f251 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -616,10 +616,7 @@
      */
 
     // destroy client resources
-    sp<LayerBaseClient> layer = getOwner();
-    if (layer != 0) {
-        mFlinger->destroySurface(layer);
-    }
+    mFlinger->destroySurface(mOwner);
 }
 
 sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 7162e47..6c49a19 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -202,10 +202,6 @@
      */
     virtual bool isProtected() const   { return false; }
 
-    /** Called from the main thread, when the surface is removed from the
-     * draw list */
-    virtual status_t ditch() { return NO_ERROR; }
-
     /** called with the state lock when the surface is removed from the
      *  current list */
     virtual void onRemoved() { };
@@ -271,7 +267,8 @@
     volatile    int32_t         mInvalidate;
                 
 
-protected:
+public:
+    // called from class SurfaceFlinger
     virtual ~LayerBase();
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e8f0328..b7a51a4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -387,6 +387,9 @@
 {
     waitForEvent();
 
+    // call Layer's destructor
+    handleDestroyLayers();
+
     // check for transactions
     if (UNLIKELY(mConsoleSignals)) {
         handleConsoleEvents();
@@ -480,49 +483,27 @@
 
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
-    Vector< sp<LayerBase> > ditchedLayers;
+    Mutex::Autolock _l(mStateLock);
+    const nsecs_t now = systemTime();
+    mDebugInTransaction = now;
 
-    /*
-     * Perform and commit the transaction
-     */
+    // Here we're guaranteed that some transaction flags are set
+    // so we can call handleTransactionLocked() unconditionally.
+    // We call getTransactionFlags(), which will also clear the flags,
+    // with mStateLock held to guarantee that mCurrentState won't change
+    // until the transaction is committed.
 
-    { // scope for the lock
-        Mutex::Autolock _l(mStateLock);
-        const nsecs_t now = systemTime();
-        mDebugInTransaction = now;
+    const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+    transactionFlags = getTransactionFlags(mask);
+    handleTransactionLocked(transactionFlags);
 
-        // Here we're guaranteed that some transaction flags are set
-        // so we can call handleTransactionLocked() unconditionally.
-        // We call getTransactionFlags(), which will also clear the flags,
-        // with mStateLock held to guarantee that mCurrentState won't change
-        // until the transaction is commited.
-
-        const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
-        transactionFlags = getTransactionFlags(mask);
-        handleTransactionLocked(transactionFlags, ditchedLayers);
-
-        mLastTransactionTime = systemTime() - now;
-        mDebugInTransaction = 0;
-        invalidateHwcGeometry();
-        // here the transaction has been committed
-    }
-
-    /*
-     * Clean-up all layers that went away
-     * (do this without the lock held)
-     */
-
-    const size_t count = ditchedLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        if (ditchedLayers[i] != 0) {
-            //LOGD("ditching layer %p", ditchedLayers[i].get());
-            ditchedLayers[i]->ditch();
-        }
-    }
+    mLastTransactionTime = systemTime() - now;
+    mDebugInTransaction = 0;
+    invalidateHwcGeometry();
+    // here the transaction has been committed
 }
 
-void SurfaceFlinger::handleTransactionLocked(
-        uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
+void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
 {
     const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
@@ -594,7 +575,6 @@
                 const sp<LayerBase>& layer(previousLayers[i]);
                 if (currentLayers.indexOf( layer ) < 0) {
                     // this layer is not visible anymore
-                    ditchedLayers.add(layer);
                     mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
                 }
             }
@@ -604,6 +584,31 @@
     commitTransaction();
 }
 
+void SurfaceFlinger::destroyLayer(LayerBase const* layer)
+{
+    Mutex::Autolock _l(mDestroyedLayerLock);
+    mDestroyedLayers.add(layer);
+    signalEvent();
+}
+
+void SurfaceFlinger::handleDestroyLayers()
+{
+    Vector<LayerBase const *> destroyedLayers;
+
+    { // scope for the lock
+        Mutex::Autolock _l(mDestroyedLayerLock);
+        destroyedLayers = mDestroyedLayers;
+        mDestroyedLayers.clear();
+    }
+
+    // call destructors without a lock held
+    const size_t count = destroyedLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        //LOGD("destroying %s", destroyedLayers[i]->getName().string());
+        delete destroyedLayers[i];
+    }
+}
+
 sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
 {
     return new FreezeLock(const_cast<SurfaceFlinger *>(this));
@@ -1377,51 +1382,26 @@
     return err;
 }
 
-status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
+status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
 {
     // called by ~ISurface() when all references are gone
-
-    class MessageDestroySurface : public MessageBase {
-        SurfaceFlinger* flinger;
-        sp<LayerBaseClient> layer;
-    public:
-        MessageDestroySurface(
-                SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer)
-            : flinger(flinger), layer(layer) { }
-        virtual bool handler() {
-            sp<LayerBaseClient> l(layer);
-            layer.clear(); // clear it outside of the lock;
-            Mutex::Autolock _l(flinger->mStateLock);
-            /*
-             * remove the layer from the current list -- chances are that it's
-             * not in the list anyway, because it should have been removed
-             * already upon request of the client (eg: window manager).
-             * However, a buggy client could have not done that.
-             * Since we know we don't have any more clients, we don't need
-             * to use the purgatory.
-             */
-            status_t err = flinger->removeLayer_l(l);
-            if (err == NAME_NOT_FOUND) {
-                // The surface wasn't in the current list, which means it was
-                // removed already, which means it is in the purgatory,
-                // and need to be removed from there.
-                // This needs to happen from the main thread since its dtor
-                // must run from there (b/c of OpenGL ES). Additionally, we
-                // can't really acquire our internal lock from
-                // destroySurface() -- see postMessage() below.
-                ssize_t idx = flinger->mLayerPurgatory.remove(l);
-                LOGE_IF(idx < 0,
-                        "layer=%p is not in the purgatory list", l.get());
-            }
-
-            LOGE_IF(err<0 && err != NAME_NOT_FOUND,
-                    "error removing layer=%p (%s)", l.get(), strerror(-err));
-            return true;
+    status_t err = NO_ERROR;
+    sp<LayerBaseClient> l(layer.promote());
+    if (l != NULL) {
+        Mutex::Autolock _l(mStateLock);
+        err = removeLayer_l(l);
+        if (err == NAME_NOT_FOUND) {
+            // The surface wasn't in the current list, which means it was
+            // removed already, which means it is in the purgatory,
+            // and need to be removed from there.
+            ssize_t idx = mLayerPurgatory.remove(l);
+            LOGE_IF(idx < 0,
+                    "layer=%p is not in the purgatory list", l.get());
         }
-    };
-
-    postMessageAsync( new MessageDestroySurface(this, layer) );
-    return NO_ERROR;
+        LOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                "error removing layer=%p (%s)", l.get(), strerror(-err));
+    }
+    return err;
 }
 
 status_t SurfaceFlinger::setClientState(
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1e16943..992861a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -227,6 +227,7 @@
     status_t addLayer(const sp<LayerBase>& layer);
     status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
     void invalidateHwcGeometry();
+    void destroyLayer(LayerBase const* layer);
 
     sp<Layer> getLayer(const sp<ISurface>& sur) const;
 
@@ -255,7 +256,7 @@
             uint32_t w, uint32_t h, uint32_t flags);
 
     status_t removeSurface(const sp<Client>& client, SurfaceID sid);
-    status_t destroySurface(const sp<LayerBaseClient>& layer);
+    status_t destroySurface(const wp<LayerBaseClient>& layer);
     status_t setClientState(const sp<Client>& client,
             int32_t count, const layer_state_t* states);
 
@@ -300,9 +301,8 @@
 private:
             void        handleConsoleEvents();
             void        handleTransaction(uint32_t transactionFlags);
-            void        handleTransactionLocked(
-                            uint32_t transactionFlags, 
-                            Vector< sp<LayerBase> >& ditchedLayers);
+            void        handleTransactionLocked(uint32_t transactionFlags);
+            void        handleDestroyLayers();
 
             void        computeVisibleRegions(
                             const LayerVector& currentLayers,
@@ -424,6 +424,11 @@
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
 
+
+                // protected by mDestroyedLayerLock;
+    mutable     Mutex                       mDestroyedLayerLock;
+                Vector<LayerBase const *>   mDestroyedLayers;
+
                 // atomic variables
                 enum {
                     eConsoleReleased = 1,
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index ce1a3b6..496c43c 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -85,12 +85,10 @@
 
 
     public synchronized DataConnectionAc getDataConnectionAc() {
-        log("getDataConnectionAc dcac=" + mDataConnectionAc);
         return mDataConnectionAc;
     }
 
     public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
-        log("setDataConnectionAc dcac=" + dcac);
         mDataConnectionAc = dcac;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 12d19a1..2e781b2 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -511,14 +511,14 @@
             log("onSetupConnectionCompleted received DataCallState: " + response);
             cid = response.cid;
             // set link properties based on data call response
-            result = response.setLinkProperties(mLinkProperties,
-                                                isOkToUseSystemPropertyDns(response));
+            result = setLinkProperties(response, mLinkProperties);
         }
 
         return result;
     }
 
-    private boolean isOkToUseSystemPropertyDns(DataCallState response) {
+    private DataCallState.SetupResult setLinkProperties(DataCallState response,
+            LinkProperties lp) {
         // Check if system property dns usable
         boolean okToUseSystemPropertyDns = false;
         String propertyPrefix = "net." + response.ifname + ".";
@@ -526,7 +526,9 @@
         dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
         dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
         okToUseSystemPropertyDns = isDnsOk(dnsServers);
-        return okToUseSystemPropertyDns;
+
+        // set link properties based on data call response
+        return response.setLinkProperties(lp, okToUseSystemPropertyDns);
     }
 
     private boolean updateLinkProperty(DataCallState newState) {
@@ -535,29 +537,25 @@
         if (newState == null) return changed;
 
         DataCallState.SetupResult result;
-        LinkProperties linkProperties = new LinkProperties();
+        LinkProperties newLp = new LinkProperties();
 
         // set link properties based on data call response
-        result = newState.setLinkProperties(linkProperties,
-                                            isOkToUseSystemPropertyDns(newState));
-
+        result = setLinkProperties(newState, newLp);
         if (result != DataCallState.SetupResult.SUCCESS) {
-            log("updateLinkProperty failed : " + result);
+            if (DBG) log("UpdateLinkProperty failed : " + result);
             return changed;
         }
+        // copy HTTP proxy as it is not part DataCallState.
+        newLp.setHttpProxy(mLinkProperties.getHttpProxy());
 
-        if (mLinkProperties != null) {
-            // Before comparison, copy HTTP proxy from the original
-            // as it is not part DataCallState.
-            linkProperties.setHttpProxy(mLinkProperties.getHttpProxy());
-            if (!mLinkProperties.equals(linkProperties)) {
-                mLinkProperties = linkProperties;
-                changed = true;
-            }
-        } else {
-            mLinkProperties = linkProperties;
+        if (DBG) log("old LP=" + mLinkProperties);
+        if (DBG) log("new LP=" + newLp);
+
+        if (mLinkProperties == null || !mLinkProperties.equals(newLp)) {
+            mLinkProperties = newLp;
             changed = true;
         }
+
         return changed;
     }
 
@@ -635,8 +633,9 @@
                     DataCallState newState = (DataCallState) msg.obj;
                     int updated = updateLinkProperty(newState) ? 1 : 0;
                     if (DBG) {
-                        log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE updated=" + updated +
-                            " newState=" + newState);
+                        log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE updated="
+                                + (updated == 1)
+                                + " newState=" + newState);
                     }
                     mAc.replyToMessage(msg,
                                    DataConnectionAc.RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE,
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 49b626e..6b4054a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -970,32 +970,6 @@
         return true;
     }
 
-    private boolean dataCallStatesHasCID (ArrayList<DataCallState> states, int cid) {
-        for (int i = 0, s = states.size() ; i < s ; i++) {
-            if (states.get(i).cid == cid) return true;
-        }
-        return false;
-    }
-
-    private boolean dataCallStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
-        for (int i = 0, s = states.size() ; i < s ; i++) {
-            if ((states.get(i).cid == cid) && (states.get(i).active != 0)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private DataCallState findDataCallStateByCID (ArrayList<DataCallState> states, int cid) {
-        for (int i = 0, s = states.size() ; i < s ; i++) {
-            if (states.get(i).cid == cid) {
-                return states.get(i);
-            }
-        }
-        return null;
-    }
-
     /**
      * Handles changes to the APN database.
      */
@@ -1023,15 +997,13 @@
     }
 
     /**
-     * @param explicitPoll if true, indicates that *we* polled for this
-     * update while state == CONNECTED rather than having it delivered
-     * via an unsolicited response (which could have happened at any
-     * previous state
+     * @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
+     * or RIL_UNSOL_DATA_CALL_LIST_CHANGED
      */
     private void onDataStateChanged (AsyncResult ar) {
         ArrayList<DataCallState> dataCallStates;
 
-        if (DBG) log("onDataStateChanged(ar) E");
+        if (DBG) log("onDataStateChanged(ar): E");
         dataCallStates = (ArrayList<DataCallState>)(ar.result);
 
         if (ar.exception != null) {
@@ -1042,78 +1014,79 @@
             return;
         }
 
+        // Create a hash map to store the dataCallState of each call id
+        // TODO: Depends on how frequent the DATA_CALL_LIST got updated,
+        //       may cache response to reduce comparison.
+        HashMap<Integer, DataCallState> response;
+        response = new HashMap<Integer, DataCallState>();
+        if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
+        for (DataCallState dc : dataCallStates) {
+            response.put(dc.cid, dc);
+            if (DBG) log("onDataStateChanged(ar): " + dc.cid + ": " + dc.toString());
+        }
+
+        // For each connected apn, check if there is a matched active
+        // data call state, which has the same link properties.
+        if (DBG) log("    ApnContext size=" + mApnContexts.values().size());
         for (ApnContext apnContext : mApnContexts.values()) {
-            onDataStateChanged(dataCallStates, apnContext);
-        }
-        if (DBG) log("onDataStateChanged(ar) X");
-    }
-
-    private void onDataStateChanged (ArrayList<DataCallState> dataCallStates,
-                                     ApnContext apnContext) {
-        if (DBG) log("onDataStateChanged(dataCallState, apnContext):  apnContext=" + apnContext);
-
-        if (apnContext == null) {
-            // Should not happen
-            if (DBG) log("onDataStateChanged(dataCallState, apnContext):  ignore apnContext=null");
-            return;
-        }
-
-        if (apnContext.getState() == State.CONNECTED) {
-            // The way things are supposed to work, the PDP list
-            // should not contain the CID after it disconnects.
-            // However, the way things really work, sometimes the PDP
-            // context is still listed with active = false, which
-            // makes it hard to distinguish an activating context from
-            // an activated-and-then deactivated one.
+            if (DBG){
+                log("onDataStateChanged(ar): " + apnContext.toString());
+                if (apnContext.getDataConnection() != null) {
+                    log("onDataStateChanged(ar): " +  apnContext.getDataConnection().toString());
+                }
+            }
             DataConnectionAc dcac = apnContext.getDataConnectionAc();
             if (dcac == null) {
-                if (DBG) log("onDataStateChanged(dataCallState, apnContext):  dcac==null BAD NEWS");
-                return;
+                continue;
             }
-            int cid = dcac.getCidSync();
-            if (!dataCallStatesHasCID(dataCallStates, cid)) {
-                // It looks like the PDP context has deactivated.
-                // Tear everything down and try to reconnect.
+            int connectionId = dcac.getCidSync();
 
-                if (DBG) {
-                    log("onDataStateChanged(dataCallStates,apnContext) " +
-                        "PDP connection has dropped. Reconnecting");
-                }
-                // Add an event log when the network drops PDP
-                int cellLocationId = getCellLocationId();
-                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
-                        TelephonyManager.getDefault().getNetworkType());
-
-                cleanUpConnection(true, apnContext);
-            } else if (!dataCallStatesHasActiveCID(dataCallStates,
-                    apnContext.getDataConnectionAc().getCidSync())) {
-
-                if (DBG) {
-                    log("onDataStateChanged(dataCallStates,apnContext) " +
-                        "PDP connection has dropped (active=false case). Reconnecting");
-                }
-
-                // Log the network drop on the event log.
-                int cellLocationId = getCellLocationId();
-                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
-                        TelephonyManager.getDefault().getNetworkType());
-
-                cleanUpConnection(true, apnContext);
-            } else {
-                // Here, data call list has active cid for given ApnContext.
-                // Check if link property has been updated.
-                DataCallState state = findDataCallStateByCID(dataCallStates,
-                                         apnContext.getDataConnectionAc().getCidSync());
-
-                if ((dcac != null) && (state != null)){
-                    if (dcac.updateLinkPropertiesDataCallStateSync(state)) {
-                        // notify data change for this apn
-                        mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
-                                                    apnContext.getApnType());
+            if (apnContext.getState() == State.CONNECTED) {
+                // The way things are supposed to work, the PDP list
+                // should not contain the CID after it disconnects.
+                // However, the way things really work, sometimes the PDP
+                // context is still listed with active = false, which
+                // makes it hard to distinguish an activating context from
+                // an activated-and-then de-activated one.
+                if (response.containsKey(connectionId)) {
+                    DataCallState newState = response.get(connectionId);
+                    if (DBG) log("onDataStateChanged(ar): Found ConnId=" + connectionId
+                            + " newState=" + newState.toString());
+                    if (newState.active != 0) {
+                        boolean changed
+                            = dcac.updateLinkPropertiesDataCallStateSync(newState);
+                        if (changed) {
+                            if (DBG) log("onDataStateChanged(ar): Found and changed, notify");
+                            mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
+                                    apnContext.getApnType());
+                            // Temporary hack, if false we'll reset connections and at this
+                            // time a transition from CDMA -> Global fails. The DEACTIVATE
+                            // fails with a GENERIC_FAILURE and the VZWINTERNET connection is
+                            // never setup. @see bug/
+                            if (SystemProperties.getBoolean("telephony.ignore-state-changes",
+                                    true)) {
+                                log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
+                                continue;
+                            }
+                        } else {
+                            if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
+                            continue;
+                        }
                     }
                 }
+
+                if (DBG) log("onDataStateChanged(ar): reset connection.");
+
+                // Add an event log when the network drops PDP
+                int cid = getCellLocationId();
+                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
+                        TelephonyManager.getDefault().getNetworkType());
+
+                cleanUpConnection(true, apnContext);
             }
         }
+
+        if (DBG) log("onDataStateChanged(ar): X");
     }
 
     private void notifyDefaultData(ApnContext apnContext) {
@@ -2143,7 +2116,7 @@
 
     @Override
     protected void log(String s) {
-        Log.d(LOG_TAG, "[GsmDCT] " + s);
+        Log.d(LOG_TAG, "[GsmDCT] "+ s);
     }
 
     @Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index 3c8432e..7bf25cf 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -38,6 +38,7 @@
         private final Paint mStrikePaint;
         private final Paint mScaledPaint;
         private final Paint mSkewPaint;
+        private final Paint mHugePaint;
 
         CustomTextView(Context c) {
             super(c);
@@ -64,6 +65,11 @@
             mSkewPaint.setAntiAlias(true);
             mSkewPaint.setTextSize(16.0f);
             mSkewPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff000000);
+
+            mHugePaint = new Paint();
+            mHugePaint.setAntiAlias(true);
+            mHugePaint.setColor(0xff000000);
+            mHugePaint.setTextSize(300f);
         }
 
         @Override
@@ -98,7 +104,9 @@
             mLargePaint.setAlpha(255);
             mLargePaint.setColor(0xff000000);
             mLargePaint.clearShadowLayer();
-            
+
+            canvas.drawText("Hello!", 500, 600, mHugePaint);
+
             canvas.drawText("Hello OpenGL renderer!", 500, 40, mStrikePaint);
             mStrikePaint.setStrikeThruText(true);
             canvas.drawText("Hello OpenGL renderer!", 500, 70, mStrikePaint);
@@ -106,7 +114,7 @@
             canvas.drawText("Hello OpenGL renderer!", 500, 100, mStrikePaint);
             mStrikePaint.setStrikeThruText(false);
             mStrikePaint.setUnderlineText(true);
-            
+
             mSkewPaint.setTextSkewX(-0.25f);
             canvas.drawText("Hello OpenGL renderer!", 980, 200, mSkewPaint);
             mSkewPaint.setTextSkewX(0.5f);
@@ -120,11 +128,12 @@
             canvas.drawText("Hello OpenGL renderer!", 500, 230, mScaledPaint);
             mScaledPaint.setTextScaleX(2.0f);
             canvas.drawText("Hello OpenGL renderer!", 500, 260, mScaledPaint);
-            
+
             canvas.save();
             canvas.clipRect(150.0f, 220.0f, 450.0f, 320.0f);
             canvas.drawText("Hello OpenGL renderer!", 100, 300, mLargePaint);
             canvas.restore();
+
         }
     }
 }
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index a2271d9..75535f8 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -142,17 +142,10 @@
         return 0;
     }
 
-    // screen layout size
-    if (getScreenLayoutSizeName(part.string(), &config)) {
-        *axis = AXIS_SCREENLAYOUTSIZE;
-        *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
-        return 0;
-    }
-
-    // screen layout long
-    if (getScreenLayoutLongName(part.string(), &config)) {
-        *axis = AXIS_SCREENLAYOUTLONG;
-        *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+    // smallest screen dp width
+    if (getSmallestScreenWidthDpName(part.string(), &config)) {
+        *axis = AXIS_SMALLESTSCREENWIDTHDP;
+        *value = config.smallestScreenWidthDp;
         return 0;
     }
 
@@ -170,6 +163,20 @@
         return 0;
     }
 
+    // screen layout size
+    if (getScreenLayoutSizeName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUTSIZE;
+        *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
+        return 0;
+    }
+
+    // screen layout long
+    if (getScreenLayoutLongName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUTLONG;
+        *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+        return 0;
+    }
+
     // orientation
     if (getOrientationName(part.string(), &config)) {
         *axis = AXIS_ORIENTATION;
@@ -257,7 +264,7 @@
 
     String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
     String8 touch, key, keysHidden, nav, navHidden, size, vers;
-    String8 uiModeType, uiModeNight, widthdp, heightdp;
+    String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
     const char *p = dir;
     const char *q;
@@ -344,8 +351,8 @@
         //printf("not region: %s\n", part.string());
     }
 
-    if (getScreenLayoutSizeName(part.string())) {
-        layoutsize = part;
+    if (getSmallestScreenWidthDpName(part.string())) {
+        smallestwidthdp = part;
 
         index++;
         if (index == N) {
@@ -353,19 +360,7 @@
         }
         part = parts[index];
     } else {
-        //printf("not screen layout size: %s\n", part.string());
-    }
-
-    if (getScreenLayoutLongName(part.string())) {
-        layoutlong = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not screen layout long: %s\n", part.string());
+        //printf("not smallest screen width dp: %s\n", part.string());
     }
 
     if (getScreenWidthDpName(part.string())) {
@@ -392,6 +387,30 @@
         //printf("not screen height dp: %s\n", part.string());
     }
 
+    if (getScreenLayoutSizeName(part.string())) {
+        layoutsize = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not screen layout size: %s\n", part.string());
+    }
+
+    if (getScreenLayoutLongName(part.string())) {
+        layoutlong = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not screen layout long: %s\n", part.string());
+    }
+
     // orientation
     if (getOrientationName(part.string())) {
         orient = part;
@@ -541,6 +560,7 @@
     this->locale = loc;
     this->screenLayoutSize = layoutsize;
     this->screenLayoutLong = layoutlong;
+    this->smallestScreenWidthDp = smallestwidthdp;
     this->screenWidthDp = widthdp;
     this->screenHeightDp = heightdp;
     this->orientation = orient;
@@ -570,14 +590,16 @@
     s += ",";
     s += this->locale;
     s += ",";
-    s += screenLayoutSize;
-    s += ",";
-    s += screenLayoutLong;
+    s += smallestScreenWidthDp;
     s += ",";
     s += screenWidthDp;
     s += ",";
     s += screenHeightDp;
     s += ",";
+    s += screenLayoutSize;
+    s += ",";
+    s += screenLayoutLong;
+    s += ",";
     s += this->orientation;
     s += ",";
     s += uiModeType;
@@ -618,13 +640,9 @@
         s += "-";
         s += locale;
     }
-    if (this->screenLayoutSize != "") {
+    if (this->smallestScreenWidthDp != "") {
         s += "-";
-        s += screenLayoutSize;
-    }
-    if (this->screenLayoutLong != "") {
-        s += "-";
-        s += screenLayoutLong;
+        s += smallestScreenWidthDp;
     }
     if (this->screenWidthDp != "") {
         s += "-";
@@ -634,6 +652,14 @@
         s += "-";
         s += screenHeightDp;
     }
+    if (this->screenLayoutSize != "") {
+        s += "-";
+        s += screenLayoutSize;
+    }
+    if (this->screenLayoutLong != "") {
+        s += "-";
+        s += screenLayoutLong;
+    }
     if (this->orientation != "") {
         s += "-";
         s += orientation;
@@ -1126,6 +1152,31 @@
     return true;
 }
 
+bool AaptGroupEntry::getSmallestScreenWidthDpName(const char* name, ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) {
+            out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
+        }
+        return true;
+    }
+
+    if (*name != 's') return false;
+    name++;
+    if (*name != 'w') return false;
+    name++;
+    const char* x = name;
+    while (*x >= '0' && *x <= '9') x++;
+    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
+    String8 xName(name, x-name);
+
+    if (out) {
+        out->smallestScreenWidthDp = (uint16_t)atoi(xName.string());
+    }
+
+    return true;
+}
+
 bool AaptGroupEntry::getScreenWidthDpName(const char* name, ResTable_config* out)
 {
     if (strcmp(name, kWildcardName) == 0) {
@@ -1206,10 +1257,11 @@
     if (v == 0) v = mnc.compare(o.mnc);
     if (v == 0) v = locale.compare(o.locale);
     if (v == 0) v = vendor.compare(o.vendor);
-    if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize);
-    if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong);
+    if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp);
     if (v == 0) v = screenWidthDp.compare(o.screenWidthDp);
     if (v == 0) v = screenHeightDp.compare(o.screenHeightDp);
+    if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize);
+    if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong);
     if (v == 0) v = orientation.compare(o.orientation);
     if (v == 0) v = uiModeType.compare(o.uiModeType);
     if (v == 0) v = uiModeNight.compare(o.uiModeNight);
@@ -1231,10 +1283,11 @@
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
     getLocaleName(locale.string(), &params);
-    getScreenLayoutSizeName(screenLayoutSize.string(), &params);
-    getScreenLayoutLongName(screenLayoutLong.string(), &params);
+    getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
     getScreenWidthDpName(screenWidthDp.string(), &params);
     getScreenHeightDpName(screenHeightDp.string(), &params);
+    getScreenLayoutSizeName(screenLayoutSize.string(), &params);
+    getScreenLayoutLongName(screenLayoutLong.string(), &params);
     getOrientationName(orientation.string(), &params);
     getUiModeTypeName(uiModeType.string(), &params);
     getUiModeNightName(uiModeNight.string(), &params);
@@ -1249,9 +1302,10 @@
     
     // Fix up version number based on specified parameters.
     int minSdk = 0;
-    if (params.screenWidthDp != ResTable_config::SCREENWIDTH_ANY
+    if (params.smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY
+            || params.screenWidthDp != ResTable_config::SCREENWIDTH_ANY
             || params.screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) {
-        minSdk = SDK_ICS;
+        minSdk = SDK_HONEYCOMB_MR2;
     } else if ((params.uiMode&ResTable_config::MASK_UI_MODE_TYPE)
                 != ResTable_config::UI_MODE_TYPE_ANY
             ||  (params.uiMode&ResTable_config::MASK_UI_MODE_NIGHT)
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index e5afd1b..65743d8 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -42,6 +42,7 @@
     AXIS_NAVHIDDEN,
     AXIS_NAVIGATION,
     AXIS_SCREENSIZE,
+    AXIS_SMALLESTSCREENWIDTHDP,
     AXIS_SCREENWIDTHDP,
     AXIS_SCREENHEIGHTDP,
     AXIS_VERSION
@@ -54,7 +55,7 @@
     SDK_ECLAIR_0_1 = 6,
     SDK_MR1 = 7,
     SDK_FROYO = 8,
-    SDK_ICS = 13,
+    SDK_HONEYCOMB_MR2 = 13,
 };
 
 /**
@@ -72,10 +73,11 @@
     String8 mnc;
     String8 locale;
     String8 vendor;
-    String8 screenLayoutSize;
-    String8 screenLayoutLong;
+    String8 smallestScreenWidthDp;
     String8 screenWidthDp;
     String8 screenHeightDp;
+    String8 screenLayoutSize;
+    String8 screenLayoutLong;
     String8 orientation;
     String8 uiModeType;
     String8 uiModeNight;
@@ -107,6 +109,7 @@
     static bool getNavigationName(const char* name, ResTable_config* out = NULL);
     static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
     static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
+    static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL);
     static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL);
     static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL);
     static bool getVersionName(const char* name, ResTable_config* out = NULL);
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index a88476e..5c5b4fd 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2607,6 +2607,9 @@
     if (!match(AXIS_SCREENSIZE, config.screenSize)) {
         return false;
     }
+    if (!match(AXIS_SMALLESTSCREENWIDTHDP, config.smallestScreenWidthDp)) {
+        return false;
+    }
     if (!match(AXIS_SCREENWIDTHDP, config.screenWidthDp)) {
         return false;
     }
@@ -2809,7 +2812,8 @@
                 ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
 
                 NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
-                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d %ddp x %ddp\n",
+                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
+                     "sw%ddp w%ddp h%ddp\n",
                       ti+1,
                       config.mcc, config.mnc,
                       config.language[0] ? config.language[0] : '-',
@@ -2825,6 +2829,7 @@
                       config.navigation,
                       config.screenWidth,
                       config.screenHeight,
+                      config.smallestScreenWidthDp,
                       config.screenWidthDp,
                       config.screenHeightDp));
                       
@@ -2849,7 +2854,8 @@
                 tHeader->entriesStart = htodl(typeSize);
                 tHeader->config = config;
                 NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
-                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d %ddp x %ddp\n",
+                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
+                     "sw%ddp w%ddp h%ddp\n",
                       ti+1,
                       tHeader->config.mcc, tHeader->config.mnc,
                       tHeader->config.language[0] ? tHeader->config.language[0] : '-',
@@ -2865,6 +2871,7 @@
                       tHeader->config.navigation,
                       tHeader->config.screenWidth,
                       tHeader->config.screenHeight,
+                      tHeader->config.smallestScreenWidthDp,
                       tHeader->config.screenWidthDp,
                       tHeader->config.screenHeightDp));
                 tHeader->config.swapHtoD();
@@ -3448,7 +3455,8 @@
     if (e == NULL) {
         if (config != NULL) {
             NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c "
-                    "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d %ddp x %ddp\n",
+                    "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
+                    "sw%ddp w%ddp h%ddp\n",
                       sourcePos.file.string(), sourcePos.line,
                       config->mcc, config->mnc,
                       config->language[0] ? config->language[0] : '-',
@@ -3463,6 +3471,7 @@
                       config->navigation,
                       config->screenWidth,
                       config->screenHeight,
+                      config->smallestScreenWidthDp,
                       config->screenWidthDp,
                       config->screenHeightDp));
         } else {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 16a61db..0757efd 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -87,7 +87,7 @@
 
     void releaseMulticastLock();
 
-    boolean setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
+    void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
 
     int getWifiApEnabledState();
 
diff --git a/wifi/java/android/net/wifi/WifiApConfigStore.java b/wifi/java/android/net/wifi/WifiApConfigStore.java
new file mode 100644
index 0000000..bb5427d
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiApConfigStore.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.Environment;
+import android.os.Message;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.UUID;
+
+import com.android.internal.R;
+
+
+/**
+ * Provides API to the WifiStateMachine for doing read/write access
+ * to soft access point configuration
+ */
+class WifiApConfigStore {
+
+    private static Context sContext;
+    private static final String TAG = "WifiApConfigStore";
+
+    private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
+        "/misc/wifi/softap.conf";
+
+    private static final int AP_CONFIG_FILE_VERSION = 1;
+
+    private static WifiConfiguration sApConfig = new WifiConfiguration();
+    private static final Object sApConfigLock = new Object();
+
+    private static FileReadWriteHandler sFileReadWriteHandler;
+    private static final int READ_AP_CONFIG               = 1;
+    private static final int WRITE_AP_CONFIG              = 2;
+
+    static void initialize(Context context) {
+        sContext = context;
+
+        /* File operations happen on a seperate thread */
+        HandlerThread configThread = new HandlerThread("WifiApConfigStore");
+        configThread.start();
+        sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper());
+        Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget();
+    }
+
+
+    static void setApConfiguration(WifiConfiguration config) {
+        synchronized (sApConfigLock) {
+            sApConfig = config;
+        }
+        Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config))
+            .sendToTarget();
+    }
+
+    static WifiConfiguration getApConfiguration() {
+        synchronized (sApConfigLock) {
+            return new WifiConfiguration(sApConfig);
+        }
+    }
+
+    /**
+     * File read/write handler
+     */
+    private static class FileReadWriteHandler extends Handler {
+
+        public FileReadWriteHandler(android.os.Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case WRITE_AP_CONFIG:
+                    writeApConfiguration((WifiConfiguration) msg.obj);
+                    break;
+                case READ_AP_CONFIG:
+                    readApConfiguration();
+                    break;
+                default:
+                    Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg);
+                    break;
+            }
+        }
+
+        private static void writeApConfiguration(final WifiConfiguration config) {
+            DataOutputStream out = null;
+            try {
+                out = new DataOutputStream(new BufferedOutputStream(
+                            new FileOutputStream(AP_CONFIG_FILE)));
+
+                out.writeInt(AP_CONFIG_FILE_VERSION);
+                out.writeUTF(config.SSID);
+                int authType = config.getAuthType();
+                out.writeInt(authType);
+                if(authType != KeyMgmt.NONE) {
+                    out.writeUTF(config.preSharedKey);
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "Error writing hotspot configuration" + e);
+            } finally {
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException e) {}
+                }
+            }
+        }
+
+        private static void readApConfiguration() {
+            DataInputStream in = null;
+            try {
+                WifiConfiguration config = new WifiConfiguration();
+                in = new DataInputStream(new BufferedInputStream(new FileInputStream(
+                                AP_CONFIG_FILE)));
+
+                int version = in.readInt();
+                if (version != 1) {
+                    Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
+                    setDefaultApConfiguration();
+                    return;
+                }
+                config.SSID = in.readUTF();
+                int authType = in.readInt();
+                config.allowedKeyManagement.set(authType);
+                if (authType != KeyMgmt.NONE) {
+                    config.preSharedKey = in.readUTF();
+                }
+                synchronized (sApConfigLock) {
+                    sApConfig = config;
+                }
+            } catch (IOException ignore) {
+                setDefaultApConfiguration();
+            } finally {
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException e) {}
+                }
+            }
+        }
+
+        /* Generate a default WPA2 based configuration with a random password.
+           We are changing the Wifi Ap configuration storage from secure settings to a
+           flat file accessible only by the system. A WPA2 based default configuration
+           will keep the device secure after the update */
+        private static void setDefaultApConfiguration() {
+            WifiConfiguration config = new WifiConfiguration();
+            config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default);
+            config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+            String randomUUID = UUID.randomUUID().toString();
+            //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+            config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
+            setApConfiguration(config);
+        }
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index d40f146..9d1bdd4 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -898,7 +898,8 @@
      */
     public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         try {
-            return mService.setWifiApEnabled(wifiConfig, enabled);
+            mService.setWifiApEnabled(wifiConfig, enabled);
+            return true;
         } catch (RemoteException e) {
             return false;
         }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 9125037..134f29f 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -200,8 +200,12 @@
     static final int CMD_START_AP                         = BASE + 21;
     /* Stop the soft access point */
     static final int CMD_STOP_AP                          = BASE + 22;
+    /* Set the soft access point configuration */
+    static final int CMD_SET_AP_CONFIG                    = BASE + 23;
+    /* Get the soft access point configuration */
+    static final int CMD_GET_AP_CONFIG                    = BASE + 24;
 
-    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 23;
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = BASE + 25;
 
     /* Supplicant events */
     /* Connection to supplicant established */
@@ -365,6 +369,10 @@
     private static final int MIN_RSSI = -200;
     private static final int MAX_RSSI = 256;
 
+    /* Constants to indicate if soft ap is running or stopped */
+    private static final int SOFT_AP_STOPPED = 0;
+    private static final int SOFT_AP_RUNNING = 1;
+
     /* Default parent state */
     private State mDefaultState = new DefaultState();
     /* Temporary initial state */
@@ -609,6 +617,17 @@
         }
     }
 
+    public void setWifiApConfiguration(WifiConfiguration config) {
+        sendMessage(obtainMessage(CMD_SET_AP_CONFIG, config));
+    }
+
+    public WifiConfiguration syncGetWifiApConfiguration(AsyncChannel channel) {
+        Message resultMsg = channel.sendMessageSynchronously(CMD_GET_AP_CONFIG);
+        WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
+        resultMsg.recycle();
+        return ret;
+    }
+
     /**
      * TODO: doc
      */
@@ -1533,7 +1552,31 @@
          */
         WifiNative.disconnectCommand();
         WifiNative.reconnectCommand();
+    }
 
+    private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) {
+        if (config == null) {
+            config = WifiApConfigStore.getApConfiguration();
+        } else {
+            WifiApConfigStore.setApConfiguration(config);
+        }
+        try {
+            if (currentStatus == SOFT_AP_STOPPED) {
+                nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+            } else if (currentStatus == SOFT_AP_RUNNING) {
+                nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Exception in softap start " + e);
+            try {
+                nwService.stopAccessPoint();
+                nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+            } catch (Exception ee) {
+                Log.e(TAG, "Exception during softap restart : " + ee);
+                return false;
+            }
+        }
+        return true;
     }
 
 
@@ -1671,6 +1714,13 @@
                 case CMD_ENABLE_BACKGROUND_SCAN:
                     mEnableBackgroundScan = (message.arg1 == 1);
                     break;
+                case CMD_SET_AP_CONFIG:
+                    WifiApConfigStore.setApConfiguration((WifiConfiguration) message.obj);
+                    break;
+                case CMD_GET_AP_CONFIG:
+                    WifiConfiguration config = WifiApConfigStore.getApConfiguration();
+                    mReplyChannel.replyToMessage(message, message.what, config);
+                    break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
                 case CMD_UNLOAD_DRIVER:
@@ -1733,6 +1783,8 @@
             // 50021 wifi_state_changed (custom|1|5)
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
+            WifiApConfigStore.initialize(mContext);
+
             if (WifiNative.isDriverLoaded()) {
                 transitionTo(mDriverLoadedState);
             }
@@ -1845,26 +1897,14 @@
                     }
                     break;
                 case CMD_START_AP:
-                    try {
-                        nwService.startAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Exception in softap start " + e);
-                        try {
-                            nwService.stopAccessPoint();
-                            nwService.startAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                        } catch (Exception ee) {
-                            Log.e(TAG, "Exception during softap restart : " + ee);
-                            sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
-                            break;
-                        }
+                    if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_STOPPED)) {
+                        Log.d(TAG, "Soft AP start successful");
+                        setWifiApState(WIFI_AP_STATE_ENABLED);
+                        transitionTo(mSoftApStartedState);
+                    } else {
+                        Log.d(TAG, "Soft AP start failed");
+                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
                     }
-                    Log.d(TAG, "Soft AP start successful");
-                    setWifiApState(WIFI_AP_STATE_ENABLED);
-                    transitionTo(mSoftApStartedState);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -3025,21 +3065,13 @@
                     break;
                 case CMD_START_AP:
                     Log.d(TAG,"SoftAP set on a running access point");
-                    try {
-                        nwService.setAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                    } catch(Exception e) {
-                        Log.e(TAG, "Exception in softap set " + e);
-                        try {
-                            nwService.stopAccessPoint();
-                            nwService.startAccessPoint((WifiConfiguration) message.obj,
-                                    mInterfaceName,
-                                    SOFTAP_IFACE);
-                        } catch (Exception ee) {
-                            Log.e(TAG, "Could not restart softap after set failed " + ee);
-                            sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
-                        }
+                    if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_RUNNING)) {
+                        Log.d(TAG, "Soft AP start successful");
+                        setWifiApState(WIFI_AP_STATE_ENABLED);
+                        transitionTo(mSoftApStartedState);
+                    } else {
+                        Log.d(TAG, "Soft AP start failed");
+                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
                     }
                     break;
                 /* Fail client mode operation when soft AP is enabled */