am 75c95e9a: am 0eb7b697: Merge changes Ib63ab95a,I585b0610,Ia84da0b5 into honeycomb-mr1

* commit '75c95e9a6d5a91b660af62f72b5a3bac0f5c3811':
  UsbManager: Hide APIs not needed for USB host or accessory support.
  Remove MtpClient class from framework and public API
  UsbDevice: Move IO related methods to new UsbDeviceConnection class
diff --git a/libs/hwui/utils/GenerationCache.h b/GenerationCache.h
similarity index 100%
rename from libs/hwui/utils/GenerationCache.h
rename to GenerationCache.h
diff --git a/api/12.xml b/api/12.xml
index a65d9c1..7835c7f 100644
--- a/api/12.xml
+++ b/api/12.xml
@@ -235596,7 +235596,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -236083,7 +236083,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -236149,7 +236149,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -236270,7 +236270,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -236639,7 +236639,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="l" type="android.webkit.WebSettings.LayoutAlgorithm">
@@ -236717,7 +236717,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="enabled" type="boolean">
@@ -236912,7 +236912,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="view" type="boolean">
@@ -237040,7 +237040,7 @@
  abstract="false"
  static="true"
  final="true"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <method name="valueOf"
@@ -237726,7 +237726,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -237748,7 +237748,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -237772,7 +237772,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -237783,7 +237783,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -238320,7 +238320,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="b" type="android.os.Bundle">
@@ -238376,7 +238376,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="b" type="android.os.Bundle">
@@ -238531,7 +238531,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="listener" type="android.webkit.WebView.PictureListener">
@@ -238803,7 +238803,7 @@
  abstract="true"
  static="true"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <method name="onNewPicture"
@@ -238813,7 +238813,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="view" type="android.webkit.WebView">
diff --git a/api/current.xml b/api/current.xml
index fb4cdde0..c0df626 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -105688,6 +105688,17 @@
  visibility="public"
 >
 </field>
+<field name="METADATA_KEY_BITRATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="METADATA_KEY_CD_TRACK_NUMBER"
  type="int"
  transient="false"
@@ -105765,6 +105776,28 @@
  visibility="public"
 >
 </field>
+<field name="METADATA_KEY_HAS_AUDIO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_HAS_VIDEO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="METADATA_KEY_MIMETYPE"
  type="int"
  transient="false"
@@ -105798,6 +105831,28 @@
  visibility="public"
 >
 </field>
+<field name="METADATA_KEY_VIDEO_HEIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="19"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_VIDEO_WIDTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="18"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="METADATA_KEY_WRITER"
  type="int"
  transient="false"
@@ -241162,7 +241217,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -241649,7 +241704,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -241715,7 +241770,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -241836,7 +241891,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -242205,7 +242260,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="l" type="android.webkit.WebSettings.LayoutAlgorithm">
@@ -242283,7 +242338,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="enabled" type="boolean">
@@ -242478,7 +242533,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="view" type="boolean">
@@ -242606,7 +242661,7 @@
  abstract="false"
  static="true"
  final="true"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <method name="valueOf"
@@ -243292,7 +243347,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -243314,7 +243369,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -243338,7 +243393,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -243349,7 +243404,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </method>
@@ -243886,7 +243941,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="b" type="android.os.Bundle">
@@ -243942,7 +243997,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="b" type="android.os.Bundle">
@@ -244097,7 +244152,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="listener" type="android.webkit.WebView.PictureListener">
@@ -244369,7 +244424,7 @@
  abstract="true"
  static="true"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <method name="onNewPicture"
@@ -244379,7 +244434,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="view" type="android.webkit.WebView">
@@ -264257,9 +264312,9 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="before" type="int">
+<parameter name="lengthBefore" type="int">
 </parameter>
-<parameter name="after" type="int">
+<parameter name="lengthAfter" type="int">
 </parameter>
 </method>
 <method name="onTextContextMenuItem"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index cab8ed2..26f375d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -221,12 +221,32 @@
 
     /** {@hide} */
     public static final int TYPE_DUMMY       = 8;
+
     /** {@hide} */
     public static final int TYPE_ETHERNET    = 9;
-    /** {@hide} TODO: Need to adjust this for WiMAX. */
-    public static final int MAX_RADIO_TYPE   = TYPE_DUMMY;
-    /** {@hide} TODO: Need to adjust this for WiMAX. */
-    public static final int MAX_NETWORK_TYPE = TYPE_DUMMY;
+    /**
+     * Over the air Adminstration.
+     * {@hide}
+     */
+    public static final int TYPE_MOBILE_FOTA = 10;
+
+    /**
+     * IP Multimedia Subsystem
+     * {@hide}
+     */
+    public static final int TYPE_MOBILE_IMS  = 11;
+
+    /**
+     * Carrier Branded Services
+     * {@hide}
+     */
+    public static final int TYPE_MOBILE_CBS  = 12;
+
+    /** {@hide} */
+    public static final int MAX_RADIO_TYPE   = TYPE_MOBILE_CBS;
+
+    /** {@hide} */
+    public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_CBS;
 
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
new file mode 100644
index 0000000..df5fdd0
--- /dev/null
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -0,0 +1,333 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.DhcpInfoInternal;
+import android.net.LinkAddress;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkStateTracker;
+import android.net.NetworkUtils;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class tracks the data connection associated with Ethernet
+ * This is a singleton class and an instance will be created by
+ * ConnectivityService.
+ * @hide
+ */
+public class EthernetDataTracker implements NetworkStateTracker {
+    private static final String NETWORKTYPE = "ETHERNET";
+    private static final String TAG = "Ethernet";
+
+    private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
+    private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
+    private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
+    private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+
+    private LinkProperties mLinkProperties;
+    private LinkCapabilities mLinkCapabilities;
+    private NetworkInfo mNetworkInfo;
+    private InterfaceObserver mInterfaceObserver;
+
+    /* For sending events to connectivity service handler */
+    private Handler mCsHandler;
+    private Context mContext;
+
+    private static EthernetDataTracker sInstance;
+    private static String mIface = "";
+
+    private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
+        private EthernetDataTracker mTracker;
+
+        InterfaceObserver(EthernetDataTracker tracker) {
+            super();
+            mTracker = tracker;
+        }
+
+        public void interfaceLinkStatusChanged(String iface, boolean up) {
+            Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+        }
+
+        public void interfaceAdded(String iface) {
+            mTracker.interfaceAdded(iface);
+        }
+
+        public void interfaceRemoved(String iface) {
+            mTracker.interfaceRemoved(iface);
+        }
+    }
+
+    private EthernetDataTracker() {
+        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
+        mLinkProperties = new LinkProperties();
+        mLinkCapabilities = new LinkCapabilities();
+
+        mNetworkInfo.setIsAvailable(false);
+        setTeardownRequested(false);
+    }
+
+    private void interfaceAdded(String iface) {
+        if (!iface.matches("eth\\d"))
+            return;
+
+        Log.d(TAG, "Adding " + iface);
+
+        synchronized(mIface) {
+            if(!mIface.isEmpty())
+                return;
+            mIface = iface;
+        }
+
+        mNetworkInfo.setIsAvailable(true);
+        Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+        msg.sendToTarget();
+
+        runDhcp();
+    }
+
+    private void interfaceRemoved(String iface) {
+        if (!iface.equals(mIface))
+            return;
+
+        Log.d(TAG, "Removing " + iface);
+
+        NetworkUtils.stopDhcp(mIface);
+
+        mLinkProperties.clear();
+        mNetworkInfo.setIsAvailable(false);
+        mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+
+        Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+        msg.sendToTarget();
+
+        msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+        msg.sendToTarget();
+
+        mIface = "";
+    }
+
+    private void runDhcp() {
+        Thread dhcpThread = new Thread(new Runnable() {
+            public void run() {
+                DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+                if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
+                    Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
+                    return;
+                }
+                mLinkProperties = dhcpInfoInternal.makeLinkProperties();
+                mLinkProperties.setInterfaceName(mIface);
+
+                mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+                Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+                msg.sendToTarget();
+            }
+        });
+        dhcpThread.start();
+    }
+
+    public static synchronized EthernetDataTracker getInstance() {
+        if (sInstance == null) sInstance = new EthernetDataTracker();
+        return sInstance;
+    }
+
+    public Object Clone() throws CloneNotSupportedException {
+        throw new CloneNotSupportedException();
+    }
+
+    public void setTeardownRequested(boolean isRequested) {
+        mTeardownRequested.set(isRequested);
+    }
+
+    public boolean isTeardownRequested() {
+        return mTeardownRequested.get();
+    }
+
+    /**
+     * Begin monitoring connectivity
+     */
+    public void startMonitoring(Context context, Handler target) {
+        mContext = context;
+        mCsHandler = target;
+
+        // register for notifications from NetworkManagement Service
+        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+        mInterfaceObserver = new InterfaceObserver(this);
+        try {
+            service.registerObserver(mInterfaceObserver);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not register InterfaceObserver " + e);
+        }
+    }
+
+    /**
+     * Disable connectivity to a network
+     * TODO: do away with return value after making MobileDataStateTracker async
+     */
+    public boolean teardown() {
+        mTeardownRequested.set(true);
+        NetworkUtils.stopDhcp(mIface);
+        return true;
+    }
+
+    /**
+     * Re-enable connectivity to a network after a {@link #teardown()}.
+     */
+    public boolean reconnect() {
+        mTeardownRequested.set(false);
+        runDhcp();
+        return true;
+    }
+
+    /**
+     * Turn the wireless radio off for a network.
+     * @param turnOn {@code true} to turn the radio on, {@code false}
+     */
+    public boolean setRadio(boolean turnOn) {
+        return true;
+    }
+
+    /**
+     * @return true - If are we currently tethered with another device.
+     */
+    public synchronized boolean isAvailable() {
+        return mNetworkInfo.isAvailable();
+    }
+
+    /**
+     * Tells the underlying networking system that the caller wants to
+     * begin using the named feature. The interpretation of {@code feature}
+     * is completely up to each networking implementation.
+     * @param feature the name of the feature to be used
+     * @param callingPid the process ID of the process that is issuing this request
+     * @param callingUid the user ID of the process that is issuing this request
+     * @return an integer value representing the outcome of the request.
+     * The interpretation of this value is specific to each networking
+     * implementation+feature combination, except that the value {@code -1}
+     * always indicates failure.
+     * TODO: needs to go away
+     */
+    public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+        return -1;
+    }
+
+    /**
+     * Tells the underlying networking system that the caller is finished
+     * using the named feature. The interpretation of {@code feature}
+     * is completely up to each networking implementation.
+     * @param feature the name of the feature that is no longer needed.
+     * @param callingPid the process ID of the process that is issuing this request
+     * @param callingUid the user ID of the process that is issuing this request
+     * @return an integer value representing the outcome of the request.
+     * The interpretation of this value is specific to each networking
+     * implementation+feature combination, except that the value {@code -1}
+     * always indicates failure.
+     * TODO: needs to go away
+     */
+    public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+        return -1;
+    }
+
+    /**
+     * @param enabled
+     */
+    public void setDataEnable(boolean enabled) {
+        Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
+    }
+
+    /**
+     * Check if private DNS route is set for the network
+     */
+    public boolean isPrivateDnsRouteSet() {
+        return mPrivateDnsRouteSet.get();
+    }
+
+    /**
+     * Set a flag indicating private DNS route is set
+     */
+    public void privateDnsRouteSet(boolean enabled) {
+        mPrivateDnsRouteSet.set(enabled);
+    }
+
+    /**
+     * Fetch NetworkInfo for the network
+     */
+    public synchronized NetworkInfo getNetworkInfo() {
+        return mNetworkInfo;
+    }
+
+    /**
+     * Fetch LinkProperties for the network
+     */
+    public synchronized LinkProperties getLinkProperties() {
+        return new LinkProperties(mLinkProperties);
+    }
+
+   /**
+     * A capability is an Integer/String pair, the capabilities
+     * are defined in the class LinkSocket#Key.
+     *
+     * @return a copy of this connections capabilities, may be empty but never null.
+     */
+    public LinkCapabilities getLinkCapabilities() {
+        return new LinkCapabilities(mLinkCapabilities);
+    }
+
+    /**
+     * Fetch default gateway address for the network
+     */
+    public int getDefaultGatewayAddr() {
+        return mDefaultGatewayAddr.get();
+    }
+
+    /**
+     * Check if default route is set
+     */
+    public boolean isDefaultRouteSet() {
+        return mDefaultRouteSet.get();
+    }
+
+    /**
+     * Set a flag indicating default route is set for the network
+     */
+    public void defaultRouteSet(boolean enabled) {
+        mDefaultRouteSet.set(enabled);
+    }
+
+    /**
+     * Return the system properties name associated with the tcp buffer sizes
+     * for this network.
+     */
+    public String getTcpBufferSizesPropName() {
+        return "net.tcp.buffersize.wifi";
+    }
+}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index b6e9751..81d62a0 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -91,7 +91,7 @@
     }
 
     public void addLinkAddress(LinkAddress address) {
-        mLinkAddresses.add(address);
+        if (address != null) mLinkAddresses.add(address);
     }
 
     public Collection<LinkAddress> getLinkAddresses() {
@@ -99,7 +99,7 @@
     }
 
     public void addDns(InetAddress dns) {
-        mDnses.add(dns);
+        if (dns != null) mDnses.add(dns);
     }
 
     public Collection<InetAddress> getDnses() {
@@ -107,7 +107,7 @@
     }
 
     public void addGateway(InetAddress gateway) {
-        mGateways.add(gateway);
+        if (gateway != null) mGateways.add(gateway);
     }
     public Collection<InetAddress> getGateways() {
         return Collections.unmodifiableCollection(mGateways);
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index e04964e..5b4da66 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -437,7 +437,8 @@
                 retValue = true;
                 break;
             case Phone.APN_REQUEST_STARTED:
-                // no need to do anything - we're already due some status update intents
+                // set IDLE here , avoid the following second FAILED not sent out
+                mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null);
                 retValue = true;
                 break;
             case Phone.APN_REQUEST_FAILED:
@@ -546,6 +547,12 @@
                 return Phone.APN_TYPE_DUN;
             case ConnectivityManager.TYPE_MOBILE_HIPRI:
                 return Phone.APN_TYPE_HIPRI;
+            case ConnectivityManager.TYPE_MOBILE_FOTA:
+                return Phone.APN_TYPE_FOTA;
+            case ConnectivityManager.TYPE_MOBILE_IMS:
+                return Phone.APN_TYPE_IMS;
+            case ConnectivityManager.TYPE_MOBILE_CBS:
+                return Phone.APN_TYPE_CBS;
             default:
                 sloge("Error mapping networkType " + netType + " to apnType.");
                 return null;
diff --git a/core/java/android/net/http/HttpsConnection.java b/core/java/android/net/http/HttpsConnection.java
index d77e9d9..84765a5 100644
--- a/core/java/android/net/http/HttpsConnection.java
+++ b/core/java/android/net/http/HttpsConnection.java
@@ -289,11 +289,9 @@
         } else {
             // if we do not have a proxy, we simply connect to the host
             try {
-                sslSock = (SSLSocket) getSocketFactory().createSocket();
-
+                sslSock = (SSLSocket) getSocketFactory().createSocket(
+                        mHost.getHostName(), mHost.getPort());
                 sslSock.setSoTimeout(SOCKET_TIMEOUT);
-                sslSock.connect(new InetSocketAddress(mHost.getHostName(),
-                        mHost.getPort()));
             } catch(IOException e) {
                 if (sslSock != null) {
                     sslSock.close();
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 62f66b6..d2d2557 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1723,6 +1723,14 @@
 
         public static final String TYPE = "type";
 
+        public static final String INACTIVE_TIMER = "inactivetimer";
+
+        // Only if enabled try Data Connection.
+        public static final String ENABLED = "enabled";
+
+        // Rules apply based on class.
+        public static final String CLASS = "class";
+
         /**
          * The protocol to be used to connect to this APN.
          *
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 186af70..95830ec 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -44,6 +44,8 @@
  */
 public class TextToSpeech {
 
+    private static final String TAG = "TextToSpeech";
+
     /**
      * Denotes a successful operation.
      */
@@ -579,29 +581,16 @@
                 mITts.addSpeech(mPackageName, text, packagename, resourceId);
                 return SUCCESS;
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addSpeech", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addSpeech", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addSpeech", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addSpeech", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addSpeech", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addSpeech", e);
             }
             return ERROR;
         }
     }
 
-
     /**
      * Adds a mapping between a string of text and a sound file. Using this, it
      * is possible to add custom pronounciations for a string of text.
@@ -626,23 +615,11 @@
                 mITts.addSpeechFile(mPackageName, text, filename);
                 return SUCCESS;
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addSpeech", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addSpeech", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addSpeech", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addSpeech", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addSpeech", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addSpeech", e);
             }
             return ERROR;
         }
@@ -683,23 +660,11 @@
                 mITts.addEarcon(mPackageName, earcon, packagename, resourceId);
                 return SUCCESS;
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addEarcon", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addEarcon", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addEarcon", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addEarcon", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addEarcon", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addEarcon", e);
             }
             return ERROR;
         }
@@ -730,23 +695,11 @@
                 mITts.addEarconFile(mPackageName, earcon, filename);
                 return SUCCESS;
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addEarcon", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addEarcon", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addEarcon", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addEarcon", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - addEarcon", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("addEarcon", e);
             }
             return ERROR;
         }
@@ -790,27 +743,15 @@
                 }
                 result = mITts.speak(mPackageName, text, queueMode, mCachedParams);
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - speak", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("speak", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - speak", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("speak", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - speak", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("speak", e);
             } finally {
                 resetCachedParams();
-                return result;
             }
+            return result;
         }
     }
 
@@ -849,27 +790,15 @@
                 }
                 result = mITts.playEarcon(mPackageName, earcon, queueMode, null);
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - playEarcon", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("playEarcon", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - playEarcon", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("playEarcon", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - playEarcon", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("playEarcon", e);
             } finally {
                 resetCachedParams();
-                return result;
             }
+            return result;
         }
     }
 
@@ -901,27 +830,15 @@
                 }
                 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams);
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - playSilence", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("playSilence", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - playSilence", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("playSilence", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - playSilence", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("playSilence", e);
             } finally {
                 resetCachedParams();
-                return result;
             }
+            return result;
         }
     }
 
@@ -939,23 +856,11 @@
             try {
                 return mITts.isSpeaking();
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - isSpeaking", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("isSpeaking", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - isSpeaking", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("isSpeaking", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("isSpeaking", e);
             }
             return false;
         }
@@ -977,26 +882,13 @@
             try {
                 result = mITts.stop(mPackageName);
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - stop", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("stop", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - stop", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("stop", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - stop", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("stop", e);
             }
+            return result;
         }
     }
 
@@ -1032,20 +924,11 @@
                     }
                 }
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("setSpeechRate", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("setSpeechRate", e);
             }
+            return result;
         }
     }
 
@@ -1077,20 +960,11 @@
                     result = SUCCESS;
                 }
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setPitch", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("setPitch", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setPitch", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("setPitch", e);
             }
+            return result;
         }
     }
 
@@ -1141,26 +1015,13 @@
                     }
                 }
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setLanguage", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("setLanguage", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setLanguage", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("setLanguage", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setLanguage", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("setLanguage", e);
             }
+            return result;
         }
     }
 
@@ -1191,23 +1052,11 @@
                             mCachedParams[Engine.PARAM_POSITION_VARIANT + 1]);
                 }
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - getLanguage", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("getLanguage", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - getLanguage", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("getLanguage", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - getLanguage", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("getLanguage", e);
             }
             return null;
         }
@@ -1233,26 +1082,13 @@
                 result = mITts.isLanguageAvailable(loc.getISO3Language(),
                         loc.getISO3Country(), loc.getVariant(), mCachedParams);
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("isLanguageAvailable", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("isLanguageAvailable", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("isLanguageAvailable", e);
             }
+            return result;
         }
     }
 
@@ -1293,27 +1129,15 @@
                 result = mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename) ?
                         SUCCESS : ERROR;
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("synthesizeToFile", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("synthesizeToFile", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("synthesizeToFile", e);
             } finally {
                 resetCachedParams();
-                return result;
             }
+            return result;
         }
     }
 
@@ -1366,26 +1190,13 @@
             try {
                 result = mITts.registerCallback(mPackageName, mITtscallback);
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - registerCallback", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("registerCallback", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - registerCallback", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("registerCallback", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - registerCallback", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("registerCallback", e);
             }
+            return result;
         }
     }
 
@@ -1409,26 +1220,13 @@
                     mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName;
                 }
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("setEngineByPackageName", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("setEngineByPackageName", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return result;
+                restart("setEngineByPackageName", e);
             }
+            return result;
         }
     }
 
@@ -1447,26 +1245,13 @@
             try {
                 engineName = mITts.getDefaultEngine();
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("getDefaultEngine", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("getDefaultEngine", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return engineName;
+                restart("getDefaultEngine", e);
             }
+            return engineName;
         }
     }
 
@@ -1486,26 +1271,23 @@
             try {
                 defaultsEnforced = mITts.areDefaultsEnforced();
             } catch (RemoteException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - areDefaultsEnforced", "RemoteException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("areDefaultsEnforced", e);
             } catch (NullPointerException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - areDefaultsEnforced", "NullPointerException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
+                restart("areDefaultsEnforced", e);
             } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                Log.e("TextToSpeech.java - areDefaultsEnforced", "IllegalStateException");
-                e.printStackTrace();
-                mStarted = false;
-                initTts();
-            } finally {
-                return defaultsEnforced;
+                restart("areDefaultsEnforced", e);
             }
+            return defaultsEnforced;
         }
     }
+
+    /**
+     * Restarts the TTS after a failure.
+     */
+    private void restart(String method, Exception e) {
+        // TTS died; restart it.
+        Log.e(TAG, method, e);
+        mStarted = false;
+        initTts();
+    }
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index a826a97..9e48eff 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -235,6 +235,8 @@
                     } else {
                         MetricAffectingSpan[] spans =
                             spanned.getSpans(spanStart, spanEnd, MetricAffectingSpan.class);
+                        spans = TextUtils.removeEmptySpans(spans, spanned,
+                                MetricAffectingSpan.class);
                         measured.addStyleRun(paint, spans, spanLen, fm);
                     }
                 }
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 90279d1..1b7f2f3 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -127,12 +127,12 @@
         boolean hasReplacement = false;
         if (text instanceof Spanned) {
             mSpanned = (Spanned) text;
-            hasReplacement = mSpanned.getSpans(start, limit,
-                    ReplacementSpan.class).length > 0;
+            ReplacementSpan[] spans = mSpanned.getSpans(start, limit, ReplacementSpan.class);
+            spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
+            hasReplacement = spans.length > 0;
         }
 
-        mCharsValid = hasReplacement || hasTabs ||
-            directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
+        mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
 
         if (mCharsValid) {
             if (mChars == null || mChars.length < mLen) {
@@ -147,10 +147,11 @@
                 // zero-width characters.
                 char[] chars = mChars;
                 for (int i = start, inext; i < limit; i = inext) {
-                    inext = mSpanned.nextSpanTransition(i, limit,
-                            ReplacementSpan.class);
-                    if (mSpanned.getSpans(i, inext, ReplacementSpan.class)
-                            .length > 0) { // transition into a span
+                    inext = mSpanned.nextSpanTransition(i, limit, ReplacementSpan.class);
+                    ReplacementSpan[] spans = mSpanned.getSpans(i, inext, ReplacementSpan.class);
+                    spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
+                    if (spans.length > 0) {
+                        // transition into a span
                         chars[i - start] = '\ufffc';
                         for (int j = i - start + 1, e = inext - start; j < e; ++j) {
                             chars[j] = '\ufeff'; // used as ZWNBS, marks positions to skip
@@ -197,7 +198,6 @@
             boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0;
 
             int segstart = runStart;
-            char[] chars = mChars;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
                 int codept = 0;
                 Bitmap bm = null;
@@ -629,6 +629,7 @@
 
             MetricAffectingSpan[] spans = mSpanned.getSpans(mStart + spanStart,
                     mStart + spanLimit, MetricAffectingSpan.class);
+            spans = TextUtils.removeEmptySpans(spans, mSpanned, MetricAffectingSpan.class);
 
             if (spans.length > 0) {
                 ReplacementSpan replacement = null;
@@ -835,6 +836,7 @@
                 mlimit = inext < measureLimit ? inext : measureLimit;
                 MetricAffectingSpan[] spans = mSpanned.getSpans(mStart + i,
                         mStart + mlimit, MetricAffectingSpan.class);
+                spans = TextUtils.removeEmptySpans(spans, mSpanned, MetricAffectingSpan.class);
 
                 if (spans.length > 0) {
                     ReplacementSpan replacement = null;
@@ -868,6 +870,7 @@
 
                     CharacterStyle[] spans = mSpanned.getSpans(mStart + j,
                             mStart + jnext, CharacterStyle.class);
+                    spans = TextUtils.removeEmptySpans(spans, mSpanned, CharacterStyle.class);
 
                     wp.set(mPaint);
                     for (int k = 0; k < spans.length; k++) {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index d5010c6..30a1f48 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -44,6 +44,7 @@
 import android.text.style.UnderlineSpan;
 import android.util.Printer;
 
+import java.lang.reflect.Array;
 import java.util.Iterator;
 import java.util.regex.Pattern;
 
@@ -54,7 +55,7 @@
 
     public static void getChars(CharSequence s, int start, int end,
                                 char[] dest, int destoff) {
-        Class c = s.getClass();
+        Class<? extends CharSequence> c = s.getClass();
 
         if (c == String.class)
             ((String) s).getChars(start, end, dest, destoff);
@@ -75,7 +76,7 @@
     }
 
     public static int indexOf(CharSequence s, char ch, int start) {
-        Class c = s.getClass();
+        Class<? extends CharSequence> c = s.getClass();
 
         if (c == String.class)
             return ((String) s).indexOf(ch, start);
@@ -84,7 +85,7 @@
     }
 
     public static int indexOf(CharSequence s, char ch, int start, int end) {
-        Class c = s.getClass();
+        Class<? extends CharSequence> c = s.getClass();
 
         if (s instanceof GetChars || c == StringBuffer.class ||
             c == StringBuilder.class || c == String.class) {
@@ -125,7 +126,7 @@
     }
 
     public static int lastIndexOf(CharSequence s, char ch, int last) {
-        Class c = s.getClass();
+        Class<? extends CharSequence> c = s.getClass();
 
         if (c == String.class)
             return ((String) s).lastIndexOf(ch, last);
@@ -142,7 +143,7 @@
 
         int end = last + 1;
 
-        Class c = s.getClass();
+        Class<? extends CharSequence> c = s.getClass();
 
         if (s instanceof GetChars || c == StringBuffer.class ||
             c == StringBuilder.class || c == String.class) {
@@ -499,6 +500,7 @@
             return new String(buf);
         }
 
+        @Override
         public String toString() {
             return subSequence(0, length()).toString();
         }
@@ -621,7 +623,7 @@
          * Read and return a new CharSequence, possibly with styles,
          * from the parcel.
          */
-        public  CharSequence createFromParcel(Parcel p) {
+        public CharSequence createFromParcel(Parcel p) {
             int kind = p.readInt();
 
             if (kind == 1)
@@ -760,7 +762,7 @@
 
             if (where >= 0)
                 tb.setSpan(sources[i], where, where + sources[i].length(),
-                           Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                           Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         for (int i = 0; i < sources.length; i++) {
@@ -1114,7 +1116,6 @@
             int remaining = commaCount + 1;
 
             int ok = 0;
-            int okRemaining = remaining;
             String okFormat = "";
 
             int w = 0;
@@ -1146,7 +1147,6 @@
 
                     if (w + moreWid <= avail) {
                         ok = i + 1;
-                        okRemaining = remaining;
                         okFormat = format;
                     }
                 }
@@ -1179,6 +1179,7 @@
                         MetricAffectingSpan.class);
                 MetricAffectingSpan[] spans = sp.getSpans(
                         spanStart, spanEnd, MetricAffectingSpan.class);
+                spans = TextUtils.removeEmptySpans(spans, sp, MetricAffectingSpan.class);
                 width += mt.addStyleRun(paint, spans, spanEnd - spanStart, null);
             }
         }
@@ -1537,6 +1538,56 @@
         return false;
     }
 
+    /**
+     * Removes empty spans from the <code>spans</code> array.
+     *
+     * When parsing a Spanned using {@link Spanned#nextSpanTransition(int, int, Class)}, empty spans
+     * will (correctly) create span transitions, and calling getSpans on a slice of text bounded by
+     * one of these transitions will (correctly) include the empty overlapping span.
+     *
+     * However, these empty spans should not be taken into account when layouting or rendering the
+     * string and this method provides a way to filter getSpans' results accordingly.
+     *
+     * @param spans A list of spans retrieved using {@link Spanned#getSpans(int, int, Class)} from
+     * the <code>spanned</code>
+     * @param spanned The Spanned from which spans were extracted
+     * @return A subset of spans where empty spans ({@link Spanned#getSpanStart(Object)}  ==
+     * {@link Spanned#getSpanEnd(Object)} have been removed. The initial order is preserved
+     * @hide
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T[] removeEmptySpans(T[] spans, Spanned spanned, Class<T> klass) {
+        T[] copy = null;
+        int count = 0;
+
+        for (int i = 0; i < spans.length; i++) {
+            final T span = spans[i];
+            final int start = spanned.getSpanStart(span);
+            final int end = spanned.getSpanEnd(span);
+
+            if (start == end) {
+                if (copy == null) {
+                    copy = (T[]) Array.newInstance(klass, spans.length - 1);
+                    System.arraycopy(spans, 0, copy, 0, i);
+                    count = i;
+                }
+            } else {
+                if (copy != null) {
+                    copy[count] = span;
+                    count++;
+                }
+            }
+        }
+
+        if (copy != null) {
+            T[] result = (T[]) Array.newInstance(klass, count);
+            System.arraycopy(copy, 0, result, 0, count);
+            return result;
+        } else {
+            return spans;
+        }
+    }
+
     private static Object sLock = new Object();
     private static char[] sTemp = null;
 }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index c7a7374..6306274 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1043,13 +1043,16 @@
     // These ids need to be in sync with enum rawResId in PlatformBridge.h
     private static final int NODOMAIN = 1;
     private static final int LOADERROR = 2;
-    private static final int DRAWABLEDIR = 3;
+    /* package */ static final int DRAWABLEDIR = 3;
     private static final int FILE_UPLOAD_LABEL = 4;
     private static final int RESET_LABEL = 5;
     private static final int SUBMIT_LABEL = 6;
     private static final int FILE_UPLOAD_NO_FILE_CHOSEN = 7;
 
-    String getRawResFilename(int id) {
+    private String getRawResFilename(int id) {
+        return getRawResFilename(id, mContext);
+    }
+    /* package */ static String getRawResFilename(int id, Context context) {
         int resid;
         switch (id) {
             case NODOMAIN:
@@ -1066,19 +1069,19 @@
                 break;
 
             case FILE_UPLOAD_LABEL:
-                return mContext.getResources().getString(
+                return context.getResources().getString(
                         com.android.internal.R.string.upload_file);
 
             case RESET_LABEL:
-                return mContext.getResources().getString(
+                return context.getResources().getString(
                         com.android.internal.R.string.reset);
 
             case SUBMIT_LABEL:
-                return mContext.getResources().getString(
+                return context.getResources().getString(
                         com.android.internal.R.string.submit);
 
             case FILE_UPLOAD_NO_FILE_CHOSEN:
-                return mContext.getResources().getString(
+                return context.getResources().getString(
                         com.android.internal.R.string.no_file_chosen);
 
             default:
@@ -1086,7 +1089,7 @@
                 return "";
         }
         TypedValue value = new TypedValue();
-        mContext.getResources().getValue(resid, value, true);
+        context.getResources().getValue(resid, value, true);
         if (id == DRAWABLEDIR) {
             String path = value.string.toString();
             int index = path.lastIndexOf('/');
diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java
index ccf3d6b..7c0e478 100644
--- a/core/java/android/webkit/WebHistoryItem.java
+++ b/core/java/android/webkit/WebHistoryItem.java
@@ -90,9 +90,7 @@
      * another item, the identifiers will be the same even if they are not the
      * same object.
      * @return The id for this item.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public int getId() {
         return mId;
     }
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 2b507fd..71d6080 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -43,10 +43,8 @@
      * SINGLE_COLUMN moves all content into one column that is the width of the
      * view.
      * NARROW_COLUMNS makes all columns no wider than the screen if possible.
-     * @deprecated This enum is now obsolete.
      */
     // XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
-    @Deprecated
     public enum LayoutAlgorithm {
         NORMAL,
         SINGLE_COLUMN,
@@ -512,18 +510,14 @@
 
     /**
      * Enables dumping the pages navigation cache to a text file.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public void setNavDump(boolean enabled) {
         mNavDump = enabled;
     }
 
     /**
      * Returns true if dumping the navigation cache is enabled.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public boolean getNavDump() {
         return mNavDump;
     }
@@ -661,9 +655,7 @@
      * Set whether the WebView uses its background for over scroll background.
      * If true, it will use the WebView's background. If false, it will use an
      * internal pattern. Default is true.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
         mUseWebViewBackgroundForOverscroll = view;
     }
@@ -671,9 +663,7 @@
     /**
      * Returns true if this WebView uses WebView's background instead of
      * internal pattern for over scroll background.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public boolean getUseWebViewBackgroundForOverscrollBackground() {
         return mUseWebViewBackgroundForOverscroll;
     }
@@ -876,9 +866,7 @@
      * WebView.
      * @param l A LayoutAlgorithm enum specifying the algorithm to use.
      * @see WebSettings.LayoutAlgorithm
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
         // XXX: This will only be affective if libwebcore was built with
         // ANDROID_LAYOUT defined.
@@ -893,9 +881,7 @@
      * @return LayoutAlgorithm enum value describing the layout algorithm
      *         being used.
      * @see WebSettings.LayoutAlgorithm
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public synchronized LayoutAlgorithm getLayoutAlgorithm() {
         return mLayoutAlgorithm;
     }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 0f24edc..7f4f103 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -51,8 +51,8 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.AbsoluteLayout.LayoutParams;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
@@ -515,7 +515,6 @@
             int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
             imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
         }
-        updateCursorControllerPositions();
     }
 
     @Override
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2124f73..aaf4a25 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -27,6 +27,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.database.DataSetObserver;
 import android.graphics.Bitmap;
@@ -851,17 +852,13 @@
     private PictureListener mPictureListener;
     /**
      * Interface to listen for new pictures as they change.
-     * @deprecated This interface is now obsolete.
      */
-    @Deprecated
     public interface PictureListener {
         /**
          * Notify the listener that the picture has changed.
          * @param view The WebView that owns the picture.
          * @param picture The new picture.
-         * @deprecated This method is now obsolete.
          */
-        @Deprecated
         public void onNewPicture(WebView view, Picture picture);
     }
 
@@ -1508,9 +1505,7 @@
 
     /**
      * Enables platform notifications of data state and proxy changes.
-     * @deprecated Obsolete - platform notifications are always enabled.
      */
-    @Deprecated
     public static void enablePlatformNotifications() {
         Network.enablePlatformNotifications();
     }
@@ -1518,9 +1513,7 @@
     /**
      * If platform notifications are enabled, this should be called
      * from the Activity's onPause() or onStop().
-     * @deprecated Obsolete - platform notifications are always enabled.
      */
-    @Deprecated
     public static void disablePlatformNotifications() {
         Network.disablePlatformNotifications();
     }
@@ -1623,9 +1616,7 @@
      * @param dest The file to store the serialized picture data. Will be
      *             overwritten with this WebView's picture data.
      * @return True if the picture was successfully saved.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public boolean savePicture(Bundle b, final File dest) {
         if (dest == null || b == null) {
             return false;
@@ -1686,9 +1677,7 @@
      * @param b A Bundle containing the saved display data.
      * @param src The file where the picture data was stored.
      * @return True if the picture was successfully restored.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public boolean restorePicture(Bundle b, File src) {
         if (src == null || b == null) {
             return false;
@@ -3631,9 +3620,7 @@
      * Set the Picture listener. This is an interface used to receive
      * notifications of a new Picture.
      * @param listener An implementation of WebView.PictureListener.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public void setPictureListener(PictureListener listener) {
         mPictureListener = listener;
     }
@@ -4987,9 +4974,7 @@
     /**
      * Use this method to put the WebView into text selection mode.
      * Do not rely on this functionality; it will be deprecated in the future.
-     * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public void emulateShiftHeld() {
         setUpSelect(false, 0, 0);
     }
@@ -7691,7 +7676,10 @@
                 }
                 case WEBCORE_INITIALIZED_MSG_ID:
                     // nativeCreate sets mNativeClass to a non-zero value
-                    nativeCreate(msg.arg1);
+                    String drawableDir = BrowserFrame.getRawResFilename(
+                            BrowserFrame.DRAWABLEDIR, mContext);
+                    AssetManager am = mContext.getAssets();
+                    nativeCreate(msg.arg1, drawableDir, am);
                     break;
                 case UPDATE_TEXTFIELD_TEXT_MSG_ID:
                     // Make sure that the textfield is currently focused
@@ -8506,10 +8494,6 @@
         mWebViewCore.sendMessage(EventHub.SET_BACKGROUND_COLOR, color);
     }
 
-    /**
-     * @deprecated This method is now obsolete.
-     */
-    @Deprecated
     public void debugDump() {
         nativeDebugDump();
         mWebViewCore.sendMessage(EventHub.DUMP_NAVTREE);
@@ -8577,7 +8561,7 @@
     private native Rect nativeCacheHitNodeBounds();
     private native int nativeCacheHitNodePointer();
     /* package */ native void nativeClearCursor();
-    private native void     nativeCreate(int ptr);
+    private native void     nativeCreate(int ptr, String drawableDir, AssetManager am);
     private native int      nativeCursorFramePointer();
     private native Rect     nativeCursorNodeBounds();
     private native int nativeCursorNodePointer();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 13b9285f..00124e1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4549,15 +4549,6 @@
         if (translate) canvas.translate(0, -cursorOffsetVertical);
     }
 
-    /**
-     * Update the positions of the CursorControllers.  Needed by WebTextView,
-     * which does not draw.
-     * @hide
-     */
-    protected void updateCursorControllerPositions() {
-        // TODO remove
-    }
-
     @Override
     public void getFocusedRect(Rect r) {
         if (mLayout == null) {
@@ -6275,15 +6266,15 @@
         }
 
         if (isFocused()) {
-            // This offsets because getInterestingRect() is in terms of
-            // viewport coordinates, but requestRectangleOnScreen()
-            // is in terms of content coordinates.
+            // This offsets because getInterestingRect() is in terms of viewport coordinates, but
+            // requestRectangleOnScreen() is in terms of content coordinates.
 
-            Rect r = new Rect(x, top, x + 1, bottom);
-            getInterestingRect(r, line);
-            r.offset(mScrollX, mScrollY);
+            if (mTempRect == null) mTempRect = new Rect();
+            mTempRect.set(x, top, x + 1, bottom);
+            getInterestingRect(mTempRect, line);
+            mTempRect.offset(mScrollX, mScrollY);
 
-            if (requestRectangleOnScreen(r)) {
+            if (requestRectangleOnScreen(mTempRect)) {
                 changed = true;
             }
         }
@@ -6756,25 +6747,21 @@
     }
 
     /**
-     * This method is called when the text is changed, in case any
-     * subclasses would like to know.
+     * This method is called when the text is changed, in case any subclasses
+     * would like to know.
      *
-     * @param text The text the TextView is displaying.
-     * @param start The offset of the start of the range of the text
-     *              that was modified.
-     * @param before The offset of the former end of the range of the
-     *               text that was modified.  If text was simply inserted,
-     *               this will be the same as <code>start</code>.
-     *               If text was replaced with new text or deleted, the
-     *               length of the old text was <code>before-start</code>.
-     * @param after The offset of the end of the range of the text
-     *              that was modified.  If text was simply deleted,
-     *              this will be the same as <code>start</code>.
-     *              If text was replaced with new text or inserted,
-     *              the length of the new text is <code>after-start</code>.
+     * Within <code>text</code>, the <code>lengthAfter</code> characters
+     * beginning at <code>start</code> have just replaced old text that had
+     * length <code>lengthBefore</code>. It is an error to attempt to make
+     * changes to <code>text</code> from this callback.
+     *
+     * @param text The text the TextView is displaying
+     * @param start The offset of the start of the range of the text that was
+     * modified
+     * @param lengthBefore The length of the former text that has been replaced
+     * @param lengthAfter The length of the replacement modified text
      */
-    protected void onTextChanged(CharSequence text,
-                                 int start, int before, int after) {
+    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
     }
 
     /**
@@ -7326,9 +7313,6 @@
                 && mText instanceof Spannable && mLayout != null) {
             boolean handled = false;
 
-            final int oldScrollX = mScrollX;
-            final int oldScrollY = mScrollY;
-
             if (mMovement != null) {
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
@@ -7345,27 +7329,20 @@
                 }
             }
 
-            if (isTextEditable() || mTextIsSelectable) {
-                if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // TODO remove
-                    // Hide insertion anchor while scrolling. Leave selection.
-                    hideInsertionPointCursorController(); // TODO any motion should hide it
+            if ((isTextEditable() || mTextIsSelectable) && touchIsFinished) {
+                // Show the IME, except when selecting in read-only text.
+                if (!mTextIsSelectable) {
+                    final InputMethodManager imm = InputMethodManager.peekInstance();
+                    handled |= imm != null && imm.showSoftInput(this, 0);
                 }
 
-                if (touchIsFinished) {
-                    // Show the IME, except when selecting in read-only text.
-                    if (!mTextIsSelectable) {
-                        final InputMethodManager imm = InputMethodManager.peekInstance();
-                        handled |= imm != null && imm.showSoftInput(this, 0);
-                    }
-
-                    boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect();
-                    if (!selectAllGotFocus && hasSelection()) {
-                        startSelectionActionMode();
-                    } else {
-                        stopSelectionActionMode();
-                        if (hasInsertionController() && !selectAllGotFocus && mText.length() > 0) {
-                            getInsertionController().show();
-                        }
+                boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect();
+                if (!selectAllGotFocus && hasSelection()) {
+                    startSelectionActionMode();
+                } else {
+                    stopSelectionActionMode();
+                    if (hasInsertionController() && !selectAllGotFocus && mText.length() > 0) {
+                        getInsertionController().show();
                     }
                 }
             }
@@ -8180,7 +8157,7 @@
             final int offset = getOffset(mLastDownPositionX, mLastDownPositionY);
             stopSelectionActionMode();
             Selection.setSelection((Spannable)mText, offset);
-            getInsertionController().show(0);
+            getInsertionController().showWithPaste();
             handled = true;
         }
 
@@ -8453,55 +8430,6 @@
         }
     }
 
-    /**
-     * A CursorController instance can be used to control a cursor in the text.
-     * It is not used outside of {@link TextView}.
-     * @hide
-     */
-    private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener {
-        /**
-         * Makes the cursor controller visible on screen. Will be drawn by {@link #draw(Canvas)}.
-         * See also {@link #hide()}.
-         */
-        public void show();
-
-        /**
-         * Hide the cursor controller from screen.
-         * See also {@link #show()}.
-         */
-        public void hide();
-
-        /**
-         * @return true if the CursorController is currently visible
-         */
-        public boolean isShowing();
-
-        /**
-         * Update the controller's position.
-         */
-        public void updatePosition(HandleView handle, int x, int y);
-
-        public void updateOffset(HandleView handle, int offset);
-
-        public void updatePosition();
-
-        public int getCurrentOffset(HandleView handle);
-
-        /**
-         * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
-         * a chance to become active and/or visible.
-         * @param event The touch event
-         */
-        public boolean onTouchEvent(MotionEvent event);
-
-        /**
-         * Called when the view is detached from window. Perform house keeping task, such as
-         * stopping Runnable thread that would otherwise keep a reference on the context, thus
-         * preventing the activity to be recycled.
-         */
-        public void onDetached();
-    }
-
     private class PastePopupMenu implements OnClickListener {
         private final PopupWindow mContainer;
         private int mPositionX;
@@ -8637,32 +8565,43 @@
         }
     }
 
-    private class HandleView extends View implements ViewTreeObserver.OnPreDrawListener {
-        private Drawable mDrawable;
+    private abstract class HandleView extends View implements ViewTreeObserver.OnPreDrawListener {
+        protected Drawable mDrawable;
         private final PopupWindow mContainer;
         // Position with respect to the parent TextView
         private int mPositionX, mPositionY;
-        private final CursorController mController;
         private boolean mIsDragging;
         // Offset from touch position to mPosition
         private float mTouchToWindowOffsetX, mTouchToWindowOffsetY;
-        private float mHotspotX;
+        protected float mHotspotX;
         // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
         private float mTouchOffsetY;
         // Where the touch position should be on the handle to ensure a maximum cursor visibility
         private float mIdealVerticalOffset;
         // Parent's (TextView) position in window
         private int mLastParentX, mLastParentY;
-        private float mDownPositionX, mDownPositionY;
         // PopupWindow container absolute position with respect to the enclosing window
         private int mContainerPositionX, mContainerPositionY;
         // Visible or not (scrolled off screen), whether or not this handle should be visible
         private boolean mIsActive = false;
-        // The insertion handle can have an associated PastePopupMenu
-        private boolean mIsInsertionHandle = false;
-        // Used to detect taps on the insertion handle, which will affect the PastePopupMenu
-        private long mTouchTimer;
-        private PastePopupMenu mPastePopupWindow;
+
+        public HandleView() {
+            super(TextView.this.mContext);
+            mContainer = new PopupWindow(TextView.this.mContext, null,
+                    com.android.internal.R.attr.textSelectHandleWindowStyle);
+            mContainer.setSplitTouchEnabled(true);
+            mContainer.setClippingEnabled(false);
+            mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+            mContainer.setContentView(this);
+
+            initDrawable();
+
+            final int handleHeight = mDrawable.getIntrinsicHeight();
+            mTouchOffsetY = -0.3f * handleHeight;
+            mIdealVerticalOffset = 0.7f * handleHeight;
+        }
+
+        protected abstract void initDrawable();
 
         // Touch-up filter: number of previous positions remembered
         private static final int HISTORY_SIZE = 5;
@@ -8703,73 +8642,10 @@
 
             if (i > 0 && i < iMax &&
                     (now - mPreviousOffsetsTimes[index]) > TOUCH_UP_FILTER_DELAY_BEFORE) {
-                mController.updateOffset(this, mPreviousOffsets[index]);
+                updateOffset(mPreviousOffsets[index]);
             }
         }
 
-        public static final int LEFT = 0;
-        public static final int CENTER = 1;
-        public static final int RIGHT = 2;
-
-        public HandleView(CursorController controller, int pos) {
-            super(TextView.this.mContext);
-            mController = controller;
-            mContainer = new PopupWindow(TextView.this.mContext, null,
-                    com.android.internal.R.attr.textSelectHandleWindowStyle);
-            mContainer.setSplitTouchEnabled(true);
-            mContainer.setClippingEnabled(false);
-            mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
-            mContainer.setContentView(this);
-
-            setPosition(pos);
-        }
-
-        private void setPosition(int pos) {
-            int handleWidth;
-            switch (pos) {
-                case LEFT: {
-                    if (mSelectHandleLeft == null) {
-                        mSelectHandleLeft = mContext.getResources().getDrawable(
-                                mTextSelectHandleLeftRes);
-                    }
-                    mDrawable = mSelectHandleLeft;
-                    handleWidth = mDrawable.getIntrinsicWidth();
-                    mHotspotX = handleWidth * 3.0f / 4.0f;
-                    break;
-                }
-
-                case RIGHT: {
-                    if (mSelectHandleRight == null) {
-                        mSelectHandleRight = mContext.getResources().getDrawable(
-                                mTextSelectHandleRightRes);
-                    }
-                    mDrawable = mSelectHandleRight;
-                    handleWidth = mDrawable.getIntrinsicWidth();
-                    mHotspotX = handleWidth / 4.0f;
-                    break;
-                }
-
-                case CENTER:
-                default: {
-                    if (mSelectHandleCenter == null) {
-                        mSelectHandleCenter = mContext.getResources().getDrawable(
-                                mTextSelectHandleRes);
-                    }
-                    mDrawable = mSelectHandleCenter;
-                    handleWidth = mDrawable.getIntrinsicWidth();
-                    mHotspotX = handleWidth / 2.0f;
-                    mIsInsertionHandle = true;
-                    break;
-                }
-            }
-
-            final int handleHeight = mDrawable.getIntrinsicHeight();
-            mTouchOffsetY = -0.3f * handleHeight;
-            mIdealVerticalOffset = 0.7f * handleHeight;
-
-            invalidate();
-        }
-
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
             setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
@@ -8781,7 +8657,7 @@
                 mContainer.update(mContainerPositionX, mContainerPositionY,
                         mRight - mLeft, mBottom - mTop);
 
-                hidePastePopupWindow();
+                hideAssociatedPopupWindow();
             } else {
                 mContainer.showAtLocation(TextView.this, 0,
                         mContainerPositionX, mContainerPositionY);
@@ -8793,10 +8669,10 @@
             }
         }
 
-        private void dismiss() {
+        protected void dismiss() {
             mIsDragging = false;
             mContainer.dismiss();
-            hidePastePopupWindow();
+            hideAssociatedPopupWindow();
         }
 
         public void hide() {
@@ -8829,9 +8705,7 @@
 
             final TextView hostView = TextView.this;
 
-            if (mTempRect == null) {
-                mTempRect = new Rect();
-            }
+            if (mTempRect == null) mTempRect = new Rect();
             final Rect clip = mTempRect;
             clip.left = compoundPaddingLeft;
             clip.top = extendedPaddingTop;
@@ -8865,18 +8739,42 @@
                     mLastParentX = mTempCoords[0];
                     mLastParentY = mTempCoords[1];
                 }
-                // Hide paste popup window as soon as the handle is dragged.
-                hidePastePopupWindow();
+
+                hideAssociatedPopupWindow();
             }
         }
 
+        public abstract int getCurrentCursorOffset();
+
+        public abstract void updateOffset(int offset);
+
+        public abstract void updatePosition(int x, int y);
+
+        protected void positionAtCursorOffset(int offset) {
+            addPositionToTouchUpFilter(offset);
+            final int width = mDrawable.getIntrinsicWidth();
+            final int height = mDrawable.getIntrinsicHeight();
+            final int line = mLayout.getLineForOffset(offset);
+            final int lineBottom = mLayout.getLineBottom(line);
+
+            final Rect bounds = sCursorControllerTempRect;
+            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
+                    TextView.this.mScrollX;
+            bounds.top = lineBottom + TextView.this.mScrollY;
+
+            bounds.right = bounds.left + width;
+            bounds.bottom = bounds.top + height;
+
+            convertFromViewportToContentCoordinates(bounds);
+            moveTo(bounds.left, bounds.top);
+        }
+
         /**
          * Updates the global container's position.
          * @return whether or not the position has actually changed
          */
         private boolean updateContainerPosition() {
-            // TODO Prevent this using different HandleView subclasses
-            mController.updateOffset(this, mController.getCurrentOffset(this));
+            positionAtCursorOffset(getCurrentCursorOffset());
             TextView.this.getLocationInWindow(mTempCoords);
             final int containerPositionX = mTempCoords[0] + mPositionX;
             final int containerPositionY = mTempCoords[1] + mPositionY;
@@ -8906,7 +8804,7 @@
                 }
 
                 // Hide paste popup as soon as the view is scrolled or moved
-                hidePastePopupWindow();
+                hideAssociatedPopupWindow();
             }
             return true;
         }
@@ -8921,20 +8819,15 @@
         public boolean onTouchEvent(MotionEvent ev) {
             switch (ev.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN: {
-                    startTouchUpFilter(mController.getCurrentOffset(this));
-                    mDownPositionX = ev.getRawX();
-                    mDownPositionY = ev.getRawY();
-                    mTouchToWindowOffsetX = mDownPositionX - mPositionX;
-                    mTouchToWindowOffsetY = mDownPositionY - mPositionY;
+                    startTouchUpFilter(getCurrentCursorOffset());
+                    mTouchToWindowOffsetX = ev.getRawX() - mPositionX;
+                    mTouchToWindowOffsetY = ev.getRawY() - mPositionY;
 
                     final int[] coords = mTempCoords;
                     TextView.this.getLocationInWindow(coords);
                     mLastParentX = coords[0];
                     mLastParentY = coords[1];
                     mIsDragging = true;
-                    if (mIsInsertionHandle) {
-                        mTouchTimer = SystemClock.uptimeMillis();
-                    }
                     break;
                 }
 
@@ -8958,27 +8851,11 @@
                     final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
                     final float newPosY = rawY - mTouchToWindowOffsetY + mTouchOffsetY;
 
-                    mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
+                    updatePosition(Math.round(newPosX), Math.round(newPosY));
                     break;
                 }
 
                 case MotionEvent.ACTION_UP:
-                    if (mIsInsertionHandle) {
-                        long delay = SystemClock.uptimeMillis() - mTouchTimer;
-                        if (delay < ViewConfiguration.getTapTimeout()) {
-                            final float deltaX = mDownPositionX - ev.getRawX();
-                            final float deltaY = mDownPositionY - ev.getRawY();
-                            final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
-                            if (distanceSquared < mSquaredTouchSlopDistance) {
-                                if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) {
-                                    // Tapping on the handle dismisses the displayed paste view,
-                                    mPastePopupWindow.hide();
-                                } else {
-                                    ((InsertionPointCursorController) mController).show(0);
-                                }
-                            }
-                        }
-                    }
                     filterOnTouchUp();
                     mIsDragging = false;
                     break;
@@ -8994,60 +8871,40 @@
             return mIsDragging;
         }
 
-        void positionAtCursor(int offset) {
-            addPositionToTouchUpFilter(offset);
-            final int width = mDrawable.getIntrinsicWidth();
-            final int height = mDrawable.getIntrinsicHeight();
-            final int line = mLayout.getLineForOffset(offset);
-            final int lineBottom = mLayout.getLineBottom(line);
-
-            final Rect bounds = sCursorControllerTempRect;
-            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
-                    TextView.this.mScrollX;
-            bounds.top = lineBottom + TextView.this.mScrollY;
-
-            bounds.right = bounds.left + width;
-            bounds.bottom = bounds.top + height;
-
-            convertFromViewportToContentCoordinates(bounds);
-            moveTo(bounds.left, bounds.top);
+        void hideAssociatedPopupWindow() {
+            // No associated popup window by default
         }
-
-        void showPastePopupWindow() {
-            if (mIsInsertionHandle) {
-                if (mPastePopupWindow == null) {
-                    // Lazy initialisation: create when actually shown only.
-                    mPastePopupWindow = new PastePopupMenu();
-                }
-                mPastePopupWindow.show();
-            }
-        }
-
-        void hidePastePopupWindow() {
-            if (mPastePopupWindow != null) {
-                mPastePopupWindow.hide();
-            }
+        
+        public void onDetached() {
+            // Should be overriden to clean possible Runnable
         }
     }
 
-    private class InsertionPointCursorController implements CursorController {
+    private class InsertionHandleView extends HandleView {
         private static final int DELAY_BEFORE_FADE_OUT = 4000;
-        private static final int DELAY_BEFORE_PASTE = 2000;
-        private static final int RECENT_CUT_COPY_DURATION = 15 * 1000;
+        private static final int RECENT_CUT_COPY_DURATION = 15 * 1000; // seconds
 
-        // The cursor controller image. Lazily created.
-        private HandleView mHandle;
+        // Used to detect taps on the insertion handle, which will affect the PastePopupMenu
+        private long mTouchTimer;
+        private float mDownPositionX, mDownPositionY;
+        private PastePopupMenu mPastePopupWindow;
         private Runnable mHider;
         private Runnable mPastePopupShower;
 
+        public InsertionHandleView() {
+            super();
+        }
+
+        @Override
         public void show() {
-            show(DELAY_BEFORE_PASTE);
+            super.show();
+            hideDelayed();
+            removePastePopupCallback();
         }
 
         public void show(int delayBeforePaste) {
-            getHandle().show();
-            hideDelayed();
-            removePastePopupCallback();
+            show();
+
             final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
             if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
                 delayBeforePaste = 0;
@@ -9056,7 +8913,7 @@
                 if (mPastePopupShower == null) {
                     mPastePopupShower = new Runnable() {
                         public void run() {
-                            getHandle().showPastePopupWindow();
+                            showAssociatedPopupWindow();
                         }
                     };
                 }
@@ -9064,24 +8921,15 @@
             }
         }
 
-        private void removePastePopupCallback() {
-            if (mPastePopupShower != null) {
-                removeCallbacks(mPastePopupShower);
-            }
+        @Override
+        protected void dismiss() {
+            super.dismiss();
+            onDetached();
         }
 
-        private void removeHiderCallback() {
-            if (mHider != null) {
-                removeCallbacks(mHider);
-            }
-        }
-
+        @Override
         public void hide() {
-            if (mHandle != null) {
-                mHandle.hide();
-            }
-            removeHiderCallback();
-            removePastePopupCallback();
+            super.hide();
         }
 
         private void hideDelayed() {
@@ -9096,41 +8944,244 @@
             postDelayed(mHider, DELAY_BEFORE_FADE_OUT);
         }
 
-        public boolean isShowing() {
-            return mHandle != null && mHandle.isShowing();
+        private void removePastePopupCallback() {
+            if (mPastePopupShower != null) {
+                removeCallbacks(mPastePopupShower);
+            }
         }
 
-        public void updatePosition(HandleView handle, int x, int y) {
-            final int previousOffset = getSelectionStart();
+        private void removeHiderCallback() {
+            if (mHider != null) {
+                removeCallbacks(mHider);
+            }
+        }
+
+        @Override
+        protected void initDrawable() {
+            if (mSelectHandleCenter == null) {
+                mSelectHandleCenter = mContext.getResources().getDrawable(
+                        mTextSelectHandleRes);
+            }
+            mDrawable = mSelectHandleCenter;
+            mHotspotX = mDrawable.getIntrinsicWidth() / 2.0f;
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent ev) {
+            final boolean result = super.onTouchEvent(ev);
+
+            switch (ev.getActionMasked()) {
+                case MotionEvent.ACTION_DOWN:
+                    mDownPositionX = ev.getRawX();
+                    mDownPositionY = ev.getRawY();
+                    mTouchTimer = SystemClock.uptimeMillis();
+                    break;
+
+                case MotionEvent.ACTION_UP:
+                    long delay = SystemClock.uptimeMillis() - mTouchTimer;
+                    if (delay < ViewConfiguration.getTapTimeout()) {
+                        final float deltaX = mDownPositionX - ev.getRawX();
+                        final float deltaY = mDownPositionY - ev.getRawY();
+                        final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
+                        if (distanceSquared < mSquaredTouchSlopDistance) {
+                            if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) {
+                                // Tapping on the handle dismisses the displayed paste view,
+                                mPastePopupWindow.hide();
+                            } else {
+                                show(0);
+                            }
+                        }
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+
+            return result;
+        }
+
+        @Override
+        public int getCurrentCursorOffset() {
+            return TextView.this.getSelectionStart();
+        }
+
+        @Override
+        public void updateOffset(int offset) {
+            Selection.setSelection((Spannable) mText, offset);
+            positionAtCursorOffset(offset);
+        }
+
+        @Override
+        public void updatePosition(int x, int y) {
+            final int previousOffset = getCurrentCursorOffset();
             final int newOffset = getOffset(x, y);
 
             if (newOffset != previousOffset) {
-                updateOffset(handle, newOffset);
+                updateOffset(newOffset);
                 removePastePopupCallback();
             }
             hideDelayed();
         }
 
-        public void updateOffset(HandleView handle, int offset) {
-            Selection.setSelection((Spannable) mText, offset);
-            updatePosition();
-        }
-
-        public void updatePosition() {
-            final int offset = getSelectionStart();
-
-            if (offset < 0) {
-                // Should never happen, safety check.
-                Log.w(LOG_TAG, "Update cursor controller position called with no cursor");
-                hide();
-                return;
+        void showAssociatedPopupWindow() {
+            if (mPastePopupWindow == null) {
+                // Lazy initialisation: create when actually shown only.
+                mPastePopupWindow = new PastePopupMenu();
             }
-
-            getHandle().positionAtCursor(offset);
+            mPastePopupWindow.show();
         }
 
-        public int getCurrentOffset(HandleView handle) {
-            return getSelectionStart();
+        @Override
+        void hideAssociatedPopupWindow() {
+            if (mPastePopupWindow != null) {
+                mPastePopupWindow.hide();
+            }
+        }
+
+        @Override
+        public void onDetached() {
+            removeHiderCallback();
+            removePastePopupCallback();
+        }
+    }
+
+    private class SelectionStartHandleView extends HandleView {
+        public SelectionStartHandleView() {
+            super();
+        }
+
+        @Override
+        protected void initDrawable() {
+            if (mSelectHandleLeft == null) {
+                mSelectHandleLeft = mContext.getResources().getDrawable(
+                        mTextSelectHandleLeftRes);
+            }
+            mDrawable = mSelectHandleLeft;
+            mHotspotX = mDrawable.getIntrinsicWidth() * 3.0f / 4.0f;
+        }
+
+        @Override
+        public int getCurrentCursorOffset() {
+            return TextView.this.getSelectionStart();
+        }
+
+        @Override
+        public void updateOffset(int offset) {
+            Selection.setSelection((Spannable) mText, offset, getSelectionEnd());
+            positionAtCursorOffset(offset);
+        }
+
+        @Override
+        public void updatePosition(int x, int y) {
+            final int selectionStart = getSelectionStart();
+            final int selectionEnd = getSelectionEnd();
+
+            int offset = getOffset(x, y);
+
+            // No need to redraw when the offset is unchanged
+            if (offset == selectionStart) return;
+            // Handles can not cross and selection is at least one character
+            if (offset >= selectionEnd) offset = selectionEnd - 1;
+
+            Selection.setSelection((Spannable) mText, offset, selectionEnd);
+            positionAtCursorOffset(offset);
+        }
+    }
+
+    private class SelectionEndHandleView extends HandleView {
+        public SelectionEndHandleView() {
+            super();
+        }
+
+        @Override
+        protected void initDrawable() {
+            if (mSelectHandleRight == null) {
+                mSelectHandleRight = mContext.getResources().getDrawable(
+                        mTextSelectHandleRightRes);
+            }
+            mDrawable = mSelectHandleRight;
+            mHotspotX = mDrawable.getIntrinsicWidth() / 4.0f;
+        }
+
+        @Override
+        public int getCurrentCursorOffset() {
+            return TextView.this.getSelectionEnd();
+        }
+
+        @Override
+        public void updateOffset(int offset) {
+            Selection.setSelection((Spannable) mText, getSelectionStart(), offset);
+            positionAtCursorOffset(offset);
+        }
+
+        @Override
+        public void updatePosition(int x, int y) {
+            final int selectionStart = getSelectionStart();
+            final int selectionEnd = getSelectionEnd();
+
+            int offset = getOffset(x, y);
+
+            // No need to redraw when the offset is unchanged
+            if (offset == selectionEnd) return;
+            // Handles can not cross and selection is at least one character
+            if (offset <= selectionStart) offset = selectionStart + 1;
+
+            Selection.setSelection((Spannable) mText, selectionStart, offset);
+            positionAtCursorOffset(offset);
+        }
+    }
+
+    /**
+     * A CursorController instance can be used to control a cursor in the text.
+     * It is not used outside of {@link TextView}.
+     * @hide
+     */
+    private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener {
+        /**
+         * Makes the cursor controller visible on screen. Will be drawn by {@link #draw(Canvas)}.
+         * See also {@link #hide()}.
+         */
+        public void show();
+
+        /**
+         * Hide the cursor controller from screen.
+         * See also {@link #show()}.
+         */
+        public void hide();
+
+        /**
+         * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
+         * a chance to become active and/or visible.
+         * @param event The touch event
+         */
+        public boolean onTouchEvent(MotionEvent event);
+
+        /**
+         * Called when the view is detached from window. Perform house keeping task, such as
+         * stopping Runnable thread that would otherwise keep a reference on the context, thus
+         * preventing the activity from being recycled.
+         */
+        public void onDetached();
+    }
+
+    private class InsertionPointCursorController implements CursorController {
+        private static final int DELAY_BEFORE_PASTE = 2000;
+
+        private InsertionHandleView mHandle;
+
+        public void show() {
+            ((InsertionHandleView) getHandle()).show(DELAY_BEFORE_PASTE);
+        }
+
+        public void showWithPaste() {
+            ((InsertionHandleView) getHandle()).show(0);
+        }
+
+        public void hide() {
+            if (mHandle != null) {
+                mHandle.hide();
+            }
         }
 
         public boolean onTouchEvent(MotionEvent ev) {
@@ -9145,30 +9196,27 @@
 
         private HandleView getHandle() {
             if (mHandle == null) {
-                mHandle = new HandleView(this, HandleView.CENTER);
+                mHandle = new InsertionHandleView();
             }
             return mHandle;
         }
 
         @Override
         public void onDetached() {
-            removeHiderCallback();
-            removePastePopupCallback();
+            if (mHandle == null) mHandle.onDetached();
         }
     }
 
     private class SelectionModifierCursorController implements CursorController {
-        // The cursor controller images, lazily created when shown.
-        private HandleView mStartHandle, mEndHandle;
+        // The cursor controller handles, lazily created when shown.
+        private SelectionStartHandleView mStartHandle;
+        private SelectionEndHandleView mEndHandle;
         // The offsets of that last touch down event. Remembered to start selection there.
         private int mMinTouchOffset, mMaxTouchOffset;
-        // Whether selection anchors are active
-        private boolean mIsShowing;
 
         // Double tap detection
         private long mPreviousTapUpTime = 0;
-        private int mPreviousTapPositionX;
-        private int mPreviousTapPositionY;
+        private int mPreviousTapPositionX, mPreviousTapPositionY;
 
         SelectionModifierCursorController() {
             resetTouchOffsets();
@@ -9180,10 +9228,8 @@
             }
 
             // Lazy object creation has to be done before updatePosition() is called.
-            if (mStartHandle == null) mStartHandle = new HandleView(this, HandleView.LEFT);
-            if (mEndHandle == null) mEndHandle = new HandleView(this, HandleView.RIGHT);
-
-            mIsShowing = true;
+            if (mStartHandle == null) mStartHandle = new SelectionStartHandleView();
+            if (mEndHandle == null) mEndHandle = new SelectionEndHandleView();
 
             mStartHandle.show();
             mEndHandle.show();
@@ -9194,82 +9240,6 @@
         public void hide() {
             if (mStartHandle != null) mStartHandle.hide();
             if (mEndHandle != null) mEndHandle.hide();
-            mIsShowing = false;
-        }
-
-        public boolean isShowing() {
-            return mIsShowing;
-        }
-
-        public void updatePosition(HandleView handle, int x, int y) {
-            int selectionStart = getSelectionStart();
-            int selectionEnd = getSelectionEnd();
-
-            int offset = getOffset(x, y);
-
-            // Handle the case where start and end are swapped, making sure start <= end
-            if (handle == mStartHandle) {
-                if (selectionStart == offset || offset > selectionEnd) {
-                    return; // no change, no need to redraw;
-                }
-                // If the user "closes" the selection entirely they were probably trying to
-                // select a single character. Help them out.
-                if (offset == selectionEnd) {
-                    offset = selectionEnd - 1;
-                }
-                selectionStart = offset;
-            } else {
-                if (selectionEnd == offset || offset < selectionStart) {
-                    return; // no change, no need to redraw;
-                }
-                // If the user "closes" the selection entirely they were probably trying to
-                // select a single character. Help them out.
-                if (offset == selectionStart) {
-                    offset = selectionStart + 1;
-                }
-                selectionEnd = offset;
-            }
-
-            Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
-            updatePosition();
-        }
-
-        public void updateOffset(HandleView handle, int offset) {
-            int start = getSelectionStart();
-            int end = getSelectionEnd();
-
-            if (mStartHandle == handle) {
-                start = offset;
-            } else {
-                end = offset;
-            }
-
-            Selection.setSelection((Spannable) mText, start, end);
-            updatePosition();
-        }
-
-        public void updatePosition() {
-            if (!isShowing()) {
-                return;
-            }
-
-            final int selectionStart = getSelectionStart();
-            final int selectionEnd = getSelectionEnd();
-
-            if ((selectionStart < 0) || (selectionEnd < 0)) {
-                // Should never happen, safety check.
-                Log.w(LOG_TAG, "Update selection controller position called with no cursor");
-                hide();
-                return;
-            }
-
-            // The handles have been created since the controller isShowing().
-            mStartHandle.positionAtCursor(selectionStart);
-            mEndHandle.positionAtCursor(selectionEnd);
-        }
-
-        public int getCurrentOffset(HandleView handle) {
-            return mStartHandle == handle ? getSelectionStart() : getSelectionEnd();
         }
 
         public boolean onTouchEvent(MotionEvent event) {
@@ -9360,7 +9330,10 @@
         }
 
         @Override
-        public void onDetached() {}
+        public void onDetached() {
+            if (mStartHandle != null) mStartHandle.onDetached();
+            if (mEndHandle != null) mEndHandle.onDetached();
+        }
     }
 
     private void hideInsertionPointCursorController() {
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index 101dd91..4d656c0c 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -135,6 +135,8 @@
      * channel is forcibly disconnected by the system or as a reply to CMD_CHANNEL_DISCONNECT.
      *
      * msg.arg1 == 0 : STATUS_SUCCESSFUL
+     *             1 : STATUS_BINDING_UNSUCCESSFUL
+     *             2 : STATUS_SEND_UNSUCCESSFUL
      *               : All other values signify failure and the channel state is indeterminate
      * msg.obj  == the AsyncChannel
      * msg.replyTo = messenger disconnecting or null if it was never connected.
@@ -147,6 +149,9 @@
     /** Error attempting to bind on a connect */
     public static final int STATUS_BINDING_UNSUCCESSFUL = 1;
 
+    /** Error attempting to send a message */
+    public static final int STATUS_SEND_UNSUCCESSFUL = 2;
+
     /** Service connection */
     private AsyncChannelConnection mConnection;
 
@@ -345,11 +350,7 @@
             mSrcContext.unbindService(mConnection);
         }
         if (mSrcHandler != null) {
-            Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
-            msg.arg1 = STATUS_SUCCESSFUL;
-            msg.obj = this;
-            msg.replyTo = mDstMessenger;
-            mSrcHandler.sendMessage(msg);
+            replyDisconnected(STATUS_SUCCESSFUL);
         }
     }
 
@@ -363,7 +364,7 @@
         try {
             mDstMessenger.send(msg);
         } catch (RemoteException e) {
-            log("TODO: handle sendMessage RemoteException" + e);
+            replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
         }
     }
 
@@ -712,6 +713,7 @@
 
     /**
      * Reply to the src handler that we're half connected.
+     * see: CMD_CHANNEL_HALF_CONNECTED for message contents
      *
      * @param status to be stored in msg.arg1
      */
@@ -724,6 +726,21 @@
     }
 
     /**
+     * Reply to the src handler that we are disconnected
+     * see: CMD_CHANNEL_DISCONNECTED for message contents
+     *
+     * @param status to be stored in msg.arg1
+     */
+    private void replyDisconnected(int status) {
+        Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
+        msg.arg1 = status;
+        msg.obj = this;
+        msg.replyTo = mDstMessenger;
+        mSrcHandler.sendMessage(msg);
+    }
+
+
+    /**
      * ServiceConnection to receive call backs.
      */
     class AsyncChannelConnection implements ServiceConnection {
@@ -736,11 +753,7 @@
         }
 
         public void onServiceDisconnected(ComponentName className) {
-            Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
-            msg.arg1 = STATUS_SUCCESSFUL;
-            msg.obj = AsyncChannel.this;
-            msg.replyTo = mDstMessenger;
-            mSrcHandler.sendMessage(msg);
+            replyDisconnected(STATUS_SUCCESSFUL);
         }
     }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 1c4dc29..52fc930 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -99,6 +99,7 @@
 	android/graphics/Movie.cpp \
 	android/graphics/NinePatch.cpp \
 	android/graphics/NinePatchImpl.cpp \
+	android/graphics/NinePatchPeeker.cpp \
 	android/graphics/Paint.cpp \
 	android/graphics/Path.cpp \
 	android/graphics/PathMeasure.cpp \
@@ -112,6 +113,7 @@
 	android/graphics/Shader.cpp \
 	android/graphics/SurfaceTexture.cpp \
 	android/graphics/TextLayout.cpp \
+	android/graphics/TextLayoutCache.cpp \
 	android/graphics/Typeface.cpp \
 	android/graphics/Utils.cpp \
 	android/graphics/Xfermode.cpp \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 491a388..1034fbd 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -1,6 +1,7 @@
 #define LOG_TAG "BitmapFactory"
 
 #include "BitmapFactory.h"
+#include "NinePatchPeeker.h"
 #include "SkImageDecoder.h"
 #include "SkImageRef_ashmem.h"
 #include "SkImageRef_GlobalPool.h"
@@ -47,65 +48,6 @@
 
 using namespace android;
 
-class NinePatchPeeker : public SkImageDecoder::Peeker {
-    SkImageDecoder* fHost;
-public:
-    NinePatchPeeker(SkImageDecoder* host) {
-        // the host lives longer than we do, so a raw ptr is safe
-        fHost = host;
-        fPatchIsValid = false;
-    }
-
-    ~NinePatchPeeker() {
-        if (fPatchIsValid) {
-            free(fPatch);
-        }
-    }
-
-    bool    fPatchIsValid;
-    Res_png_9patch*  fPatch;
-
-    virtual bool peek(const char tag[], const void* data, size_t length) {
-        if (strcmp("npTc", tag) == 0 && length >= sizeof(Res_png_9patch)) {
-            Res_png_9patch* patch = (Res_png_9patch*) data;
-            size_t patchSize = patch->serializedSize();
-            assert(length == patchSize);
-            // You have to copy the data because it is owned by the png reader
-            Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
-            memcpy(patchNew, patch, patchSize);
-            // this relies on deserialization being done in place
-            Res_png_9patch::deserialize(patchNew);
-            patchNew->fileToDevice();
-            if (fPatchIsValid) {
-                free(fPatch);
-            }
-            fPatch = patchNew;
-            //printf("9patch: (%d,%d)-(%d,%d)\n",
-            //       fPatch.sizeLeft, fPatch.sizeTop,
-            //       fPatch.sizeRight, fPatch.sizeBottom);
-            fPatchIsValid = true;
-
-            // now update our host to force index or 32bit config
-            // 'cause we don't want 565 predithered, since as a 9patch, we know
-            // we will be stretched, and therefore we want to dither afterwards.
-            static const SkBitmap::Config gNo565Pref[] = {
-                SkBitmap::kIndex8_Config,
-                SkBitmap::kIndex8_Config,
-                SkBitmap::kARGB_8888_Config,
-                SkBitmap::kARGB_8888_Config,
-                SkBitmap::kARGB_8888_Config,
-                SkBitmap::kARGB_8888_Config,
-            };
-            fHost->setPrefConfigTable(gNo565Pref);
-        } else {
-            fPatch = NULL;
-        }
-        return true;    // keep on decoding
-    }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
 static inline int32_t validOrNeg1(bool isValid, int32_t value) {
 //    return isValid ? value : -1;
     SkASSERT((int)isValid == 0 || (int)isValid == 1);
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
new file mode 100644
index 0000000..365d985
--- /dev/null
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#include "NinePatchPeeker.h"
+
+#include "SkBitmap.h"
+
+using namespace android;
+
+bool NinePatchPeeker::peek(const char tag[], const void* data, size_t length) {
+    if (strcmp("npTc", tag) == 0 && length >= sizeof(Res_png_9patch)) {
+        Res_png_9patch* patch = (Res_png_9patch*) data;
+        size_t patchSize = patch->serializedSize();
+        assert(length == patchSize);
+        // You have to copy the data because it is owned by the png reader
+        Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
+        memcpy(patchNew, patch, patchSize);
+        // this relies on deserialization being done in place
+        Res_png_9patch::deserialize(patchNew);
+        patchNew->fileToDevice();
+        if (fPatchIsValid) {
+            free(fPatch);
+        }
+        fPatch = patchNew;
+        //printf("9patch: (%d,%d)-(%d,%d)\n",
+        //       fPatch.sizeLeft, fPatch.sizeTop,
+        //       fPatch.sizeRight, fPatch.sizeBottom);
+        fPatchIsValid = true;
+
+        // now update our host to force index or 32bit config
+        // 'cause we don't want 565 predithered, since as a 9patch, we know
+        // we will be stretched, and therefore we want to dither afterwards.
+        static const SkBitmap::Config gNo565Pref[] = {
+            SkBitmap::kIndex8_Config,
+            SkBitmap::kIndex8_Config,
+            SkBitmap::kARGB_8888_Config,
+            SkBitmap::kARGB_8888_Config,
+            SkBitmap::kARGB_8888_Config,
+            SkBitmap::kARGB_8888_Config,
+        };
+        fHost->setPrefConfigTable(gNo565Pref);
+    } else {
+        fPatch = NULL;
+    }
+    return true;    // keep on decoding
+}
diff --git a/core/jni/android/graphics/NinePatchPeeker.h b/core/jni/android/graphics/NinePatchPeeker.h
new file mode 100644
index 0000000..8567e23
--- /dev/null
+++ b/core/jni/android/graphics/NinePatchPeeker.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef NinePatchPeeker_h
+#define NinePatchPeeker_h
+
+#include "SkImageDecoder.h"
+#include <utils/ResourceTypes.h>
+
+using namespace android;
+
+class NinePatchPeeker : public SkImageDecoder::Peeker {
+    SkImageDecoder* fHost;
+public:
+    NinePatchPeeker(SkImageDecoder* host) {
+        // the host lives longer than we do, so a raw ptr is safe
+        fHost = host;
+        fPatchIsValid = false;
+    }
+
+    ~NinePatchPeeker() {
+        if (fPatchIsValid) {
+            free(fPatch);
+        }
+    }
+
+    bool    fPatchIsValid;
+    Res_png_9patch*  fPatch;
+
+    virtual bool peek(const char tag[], const void* data, size_t length);
+};
+
+#endif // NinePatchPeeker_h
diff --git a/core/jni/android/graphics/RtlProperties.h b/core/jni/android/graphics/RtlProperties.h
new file mode 100644
index 0000000..6d8ba91
--- /dev/null
+++ b/core/jni/android/graphics/RtlProperties.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RTL_PROPERTIES_H
+#define ANDROID_RTL_PROPERTIES_H
+
+#include <cutils/properties.h>
+#include <stdlib.h>
+
+namespace android {
+
+/**
+ * Debug level for app developers.
+ */
+#define RTL_PROPERTY_DEBUG "rtl.debug_level"
+
+/**
+ * Debug levels. Debug levels are used as flags.
+ */
+enum RtlDebugLevel {
+    kRtlDebugDisabled = 0,
+    kRtlDebugMemory = 1,
+    kRtlDebugCaches = 2,
+    kRtlDebugAllocations = 3
+};
+
+static RtlDebugLevel readRtlDebugLevel() {
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(RTL_PROPERTY_DEBUG, property, NULL) > 0) {
+        return (RtlDebugLevel) atoi(property);
+    }
+    return kRtlDebugDisabled;
+}
+
+} // namespace android
+#endif // ANDROID_RTL_PROPERTIES_H
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp
index e957635..f1bb696 100644
--- a/core/jni/android/graphics/TextLayout.cpp
+++ b/core/jni/android/graphics/TextLayout.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "TextLayout.h"
+#include "TextLayoutCache.h"
 
 #include <android_runtime/AndroidRuntime.h>
 
@@ -23,10 +24,12 @@
 #include "unicode/ushape.h"
 #include <utils/Log.h>
 
-// Log debug messages from RTL related allocations
-#define DEBUG_RTL_ALLOCATIONS 0
-
 namespace android {
+
+#if USE_TEXT_LAYOUT_CACHE
+TextLayoutCache TextLayout::mCache;
+#endif
+
 // Returns true if we might need layout.  If bidiFlags force LTR, assume no layout, if
 // bidiFlags indicate there probably is RTL, assume we do, otherwise scan the text
 // looking for a character >= the first RTL character in unicode and assume we do if
@@ -60,14 +63,10 @@
  * @return the length of the shaped text, or -1 if error
  */
 int TextLayout::shapeRtlText(const jchar* context, jsize start, jsize count, jsize contextCount,
-                        jchar* shaped, UErrorCode &status) {
+                        jchar* shaped, UErrorCode& status) {
     SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
     jchar* buffer = tempBuffer.get();
 
-#if DEBUG_RTL_ALLOCATIONS
-    LOGD("TextLayout::shapeRtlText - allocated buffer with size: %d", contextCount);
-#endif
-
     // Use fixed length since we need to keep start and count valid
     u_shapeArabic(context, contextCount, buffer, contextCount,
                    U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
@@ -105,8 +104,8 @@
  * @flags line bidi flags
  * @return the length of the reordered, shaped line, or -1 if error
  */
-jint TextLayout::layoutLine(const jchar* text, jint len, jint flags, int &dir, jchar* buffer,
-        UErrorCode &status) {
+jint TextLayout::layoutLine(const jchar* text, jint len, jint flags, int& dir, jchar* buffer,
+        UErrorCode& status) {
     static const int RTL_OPTS = UBIDI_DO_MIRRORING | UBIDI_KEEP_BASE_COMBINING |
             UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_OUTPUT_REVERSE;
 
@@ -156,7 +155,7 @@
     return result;
 }
 
-bool TextLayout::prepareText(SkPaint *paint, const jchar* text, jsize len, jint bidiFlags,
+bool TextLayout::prepareText(SkPaint* paint, const jchar* text, jsize len, jint bidiFlags,
         const jchar** outText, int32_t* outBytes, jchar** outBuffer) {
     const jchar *workText = text;
     jchar *buffer = NULL;
@@ -166,11 +165,6 @@
         if (!buffer) {
             return false;
         }
-
-#if DEBUG_RTL_ALLOCATIONS
-    LOGD("TextLayout::prepareText - allocated buffer with size: %d", len);
-#endif
-
         UErrorCode status = U_ZERO_ERROR;
         len = layoutLine(text, len, bidiFlags, dir, buffer, status); // might change len, dir
         if (!U_SUCCESS(status)) {
@@ -178,7 +172,6 @@
             free(buffer);
             return false; // can't render
         }
-
         workText = buffer; // use the shaped text
     }
 
@@ -262,74 +255,24 @@
      }
  }
 
-void TextLayout::getTextRunAdvances(SkPaint *paint, const jchar *chars, jint start,
+void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
                                     jint count, jint contextCount, jint dirFlags,
-                                    jfloat *resultAdvances, jfloat &resultTotalAdvance) {
-    resultTotalAdvance = 0;
-
-    SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
-    jchar* buffer = tempBuffer.get();
-
-#if DEBUG_RTL_ALLOCATIONS
-    LOGD("TextLayout::getTextRunAdvances - allocated buffer with size: %d", contextCount);
+                                    jfloat* resultAdvances, jfloat& resultTotalAdvance) {
+#if USE_TEXT_LAYOUT_CACHE
+    // Return advances from the cache. Compute them if needed
+    mCache.getRunAdvances(paint, chars, start, count, contextCount,
+            dirFlags, resultAdvances, &resultTotalAdvance);
+#else
+    // Compute advances and return them
+    RunAdvanceDescription::computeAdvances(paint, chars, start, count, contextCount, dirFlags,
+            resultAdvances, &resultTotalAdvance);
 #endif
-
-    SkScalar* scalarArray = (SkScalar*)resultAdvances;
-
-    // this is where we'd call harfbuzz
-    // for now we just use ushape.c
-
-    int widths;
-    const jchar* text;
-    if (dirFlags & 0x1) { // rtl, call arabic shaping in case
-        UErrorCode status = U_ZERO_ERROR;
-        // Use fixed length since we need to keep start and count valid
-        u_shapeArabic(chars, contextCount, buffer, contextCount,
-                      U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
-                      U_SHAPE_TEXT_DIRECTION_LOGICAL | U_SHAPE_LETTERS_SHAPE |
-                      U_SHAPE_X_LAMALEF_SUB_ALTERNATE, &status);
-        // we shouldn't fail unless there's an out of memory condition,
-        // in which case we're hosed anyway
-        for (int i = start, e = i + count; i < e; ++i) {
-          if (buffer[i] == UNICODE_NOT_A_CHAR) {
-            buffer[i] = UNICODE_ZWSP; // zero-width-space for skia
-          }
-        }
-        text = buffer + start;
-        widths = paint->getTextWidths(text, count << 1, scalarArray);
-    } else {
-        text = chars + start;
-        widths = paint->getTextWidths(text, count << 1, scalarArray);
-    }
-
-    if (widths < count) {
-        // Skia operates on code points, not code units, so surrogate pairs return only
-        // one value. Expand the result so we have one value per UTF-16 code unit.
-
-        // Note, skia's getTextWidth gets confused if it encounters a surrogate pair,
-        // leaving the remaining widths zero.  Not nice.
-        for (int i = 0, p = 0; i < widths; ++i) {
-            resultTotalAdvance += resultAdvances[p++] = SkScalarToFloat(scalarArray[i]);
-            if (p < count &&
-                    text[p] >= UNICODE_FIRST_LOW_SURROGATE &&
-                    text[p] < UNICODE_FIRST_PRIVATE_USE &&
-                    text[p-1] >= UNICODE_FIRST_HIGH_SURROGATE &&
-                    text[p-1] < UNICODE_FIRST_LOW_SURROGATE) {
-                resultAdvances[p++] = 0;
-            }
-        }
-    } else {
-        for (int i = 0; i < count; i++) {
-            resultTotalAdvance += resultAdvances[i] = SkScalarToFloat(scalarArray[i]);
-        }
-    }
 }
 
 
 // Draws a paragraph of text on a single line, running bidi and shaping
 void TextLayout::drawText(SkPaint* paint, const jchar* text, jsize len,
                           int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas) {
-
     handleText(paint, text, len, bidiFlags, x, y, canvas, NULL);
 }
 
@@ -353,10 +296,6 @@
 
     SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> buffer(count);
 
-#if DEBUG_RTL_ALLOCATIONS
-    LOGD("TextLayout::drawTextOnPath - allocated buffer with size: %d", count);
-#endif
-
     int dir = kDirection_LTR;
     UErrorCode status = U_ZERO_ERROR;
     count = layoutLine(text, count, bidiFlags, dir, buffer.get(), status);
diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h
index c98f745..a950d13 100644
--- a/core/jni/android/graphics/TextLayout.h
+++ b/core/jni/android/graphics/TextLayout.h
@@ -20,6 +20,8 @@
 #include "SkPaint.h"
 #include "unicode/utypes.h"
 
+#include "TextLayoutCache.h"
+
 namespace android {
 
 #define UNICODE_NOT_A_CHAR              0xffff
@@ -34,6 +36,11 @@
  */
 #define CHAR_BUFFER_SIZE 80
 
+/**
+ * Turn on for using the Cache
+ */
+#define USE_TEXT_LAYOUT_CACHE 1
+
 class TextLayout {
 public:
 
@@ -62,22 +69,23 @@
                             jint start, jint count, jint contextCount,
                             int dirFlags, jfloat x, jfloat y, SkCanvas* canvas);
 
-    static void getTextRunAdvances(SkPaint *paint, const jchar *chars, jint start,
+    static void getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
                                    jint count, jint contextCount, jint dirFlags,
-                                   jfloat *resultAdvances, jfloat &resultTotalAdvance);
+                                   jfloat* resultAdvances, jfloat& resultTotalAdvance);
 
     static void drawText(SkPaint* paint, const jchar* text, jsize len,
                          jint bidiFlags, jfloat x, jfloat y, SkCanvas* canvas);
 
-    static void getTextPath(SkPaint *paint, const jchar *text, jsize len,
-                            jint bidiFlags, jfloat x, jfloat y, SkPath *path);
+    static void getTextPath(SkPaint* paint, const jchar* text, jsize len,
+                            jint bidiFlags, jfloat x, jfloat y, SkPath* path);
 
     static void drawTextOnPath(SkPaint* paint, const jchar* text, jsize len,
                                int bidiFlags, jfloat hOffset, jfloat vOffset,
                                SkPath* path, SkCanvas* canvas);
                                
-   static bool prepareText(SkPaint *paint, const jchar* text, jsize len, jint bidiFlags,
+    static bool prepareText(SkPaint* paint, const jchar* text, jsize len, jint bidiFlags,
         const jchar** outText, int32_t* outBytes, jchar** outBuffer);
+
     static bool prepareRtlTextRun(const jchar* context, jsize start, jsize& count,
         jsize contextCount, jchar* shaped);
         
@@ -85,11 +93,15 @@
 private:
     static bool needsLayout(const jchar* text, jint len, jint bidiFlags);
     static int shapeRtlText(const jchar* context, jsize start, jsize count, jsize contextCount,
-                            jchar* shaped, UErrorCode &status);
+                            jchar* shaped, UErrorCode& status);
     static jint layoutLine(const jchar* text, jint len, jint flags, int &dir, jchar* buffer,
                            UErrorCode &status);
-    static void handleText(SkPaint *paint, const jchar* text, jsize len,
-                           int bidiFlags, jfloat x, jfloat y,SkCanvas *canvas, SkPath *path);
+    static void handleText(SkPaint* paint, const jchar* text, jsize len,
+                           int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas, SkPath* path);
+
+#if USE_TEXT_LAYOUT_CACHE
+    static TextLayoutCache mCache;
+#endif
 };
 
 }
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
new file mode 100644
index 0000000..7888769
--- /dev/null
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#include "TextLayoutCache.h"
+
+namespace android {
+
+TextLayoutCache::TextLayoutCache():
+        mCache(GenerationCache<TextLayoutCacheKey, RunAdvanceDescription*>::kUnlimitedCapacity),
+        mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)),
+        mCacheHitCount(0), mNanosecondsSaved(0) {
+    init();
+}
+
+TextLayoutCache::TextLayoutCache(uint32_t max):
+        mCache(GenerationCache<TextLayoutCacheKey, RunAdvanceDescription*>::kUnlimitedCapacity),
+        mSize(0), mMaxSize(max),
+        mCacheHitCount(0), mNanosecondsSaved(0) {
+    init();
+}
+
+TextLayoutCache::~TextLayoutCache() {
+    mCache.clear();
+}
+
+void TextLayoutCache::init() {
+    mCache.setOnEntryRemovedListener(this);
+
+    mDebugLevel = readRtlDebugLevel();
+    mDebugEnabled = mDebugLevel & kRtlDebugCaches;
+    LOGD("Using TextLayoutCache debug level: %d - Debug Enabled: %d", mDebugLevel, mDebugEnabled);
+
+    mCacheStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+    if (mDebugEnabled) {
+        LOGD("TextLayoutCache start time: %lld", mCacheStartTime);
+    }
+
+    mInitialized = true;
+    if (mDebugEnabled) {
+        LOGD("TextLayoutCache initialization is done");
+    }
+}
+
+/*
+ * Size management
+ */
+
+uint32_t TextLayoutCache::getSize() {
+    return mSize;
+}
+
+uint32_t TextLayoutCache::getMaxSize() {
+    return mMaxSize;
+}
+
+void TextLayoutCache::setMaxSize(uint32_t maxSize) {
+    mMaxSize = maxSize;
+    removeOldests();
+}
+
+void TextLayoutCache::removeOldests() {
+    while (mSize > mMaxSize) {
+        mCache.removeOldest();
+    }
+}
+
+/**
+ *  Callbacks
+ */
+void TextLayoutCache::operator()(TextLayoutCacheKey& text, RunAdvanceDescription*& desc) {
+    if (desc) {
+        size_t totalSizeToDelete = text.getSize() + desc->getSize();
+        mSize -= totalSizeToDelete;
+        if (mDebugEnabled) {
+            LOGD("RunAdvance description deleted, size = %d", totalSizeToDelete);
+        }
+        delete desc;
+    }
+}
+
+/*
+ * Cache clearing
+ */
+void TextLayoutCache::clear() {
+    mCache.clear();
+}
+
+/*
+ * Caching
+ */
+void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text,
+        jint start, jint count, jint contextCount, jint dirFlags,
+        jfloat* outAdvances, jfloat* outTotalAdvance) {
+
+    AutoMutex _l(mLock);
+
+    nsecs_t startTime = 0;
+    if (mDebugEnabled) {
+        startTime = systemTime(SYSTEM_TIME_MONOTONIC);
+    }
+
+    TextLayoutCacheKey entry(paint, text, start, count, contextCount, dirFlags);
+
+    // Get entry for cache if possible
+    RunAdvanceDescription* desc = mCache.get(entry);
+
+    // Value not found for the entry, we need to add a new value in the cache
+    if (!desc) {
+        desc = new RunAdvanceDescription();
+
+        // Compute advances and store them
+        desc->computeAdvances(paint, text, start, count, contextCount, dirFlags);
+        desc->copyResult(outAdvances, outTotalAdvance);
+
+        // Don't bother to add in the cache if the entry is too big
+        size_t size = entry.getSize() + desc->getSize();
+        if (size <= mMaxSize) {
+            // Cleanup to make some room if needed
+            if (mSize + size > mMaxSize) {
+                if (mDebugEnabled) {
+                    LOGD("TextLayoutCache: need to clean some entries "
+                            "for making some room for a new entry");
+                }
+                while (mSize + size > mMaxSize) {
+                    // This will call the callback
+                    mCache.removeOldest();
+                }
+            }
+
+            // Update current cache size
+            mSize += size;
+
+            // Copy the text when we insert the new entry
+            entry.internalTextCopy();
+            mCache.put(entry, desc);
+
+            if (mDebugEnabled) {
+                // Update timing information for statistics.
+                desc->setElapsedTime(systemTime(SYSTEM_TIME_MONOTONIC) - startTime);
+
+                LOGD("CACHE MISS: Added entry for text='%s' with start=%d, count=%d, "
+                        "contextCount=%d, entry size %d bytes, remaining space %d bytes"
+                        " - Compute time in nanos: %d",
+                        String8(text, contextCount).string(), start, count, contextCount,
+                        size, mMaxSize - mSize, desc->getElapsedTime());
+            }
+        } else {
+            if (mDebugEnabled) {
+                LOGD("CACHE MISS: Calculated but not storing entry because it is too big "
+                        "for text='%s' with start=%d, count=%d, contextCount=%d, "
+                        "entry size %d bytes, remaining space %d bytes"
+                        " - Compute time in nanos: %d",
+                        String8(text, contextCount).string(), start, count, contextCount,
+                        size, mMaxSize - mSize, desc->getElapsedTime());
+            }
+            delete desc;
+        }
+    } else {
+        // This is a cache hit, just copy the pre-computed results
+        desc->copyResult(outAdvances, outTotalAdvance);
+        if (mDebugEnabled) {
+            nsecs_t elapsedTimeThruCacheGet = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
+            mNanosecondsSaved += (desc->getElapsedTime() - elapsedTimeThruCacheGet);
+            ++mCacheHitCount;
+
+            if (desc->getElapsedTime() > 0) {
+                float deltaPercent = 100 * ((desc->getElapsedTime() - elapsedTimeThruCacheGet)
+                        / ((float)desc->getElapsedTime()));
+                LOGD("CACHE HIT #%d for text='%s' with start=%d, count=%d, contextCount=%d "
+                        "- Compute time in nanos: %d - "
+                        "Cache get time in nanos: %lld - Gain in percent: %2.2f",
+                        mCacheHitCount, String8(text, contextCount).string(), start, count,
+                        contextCount,
+                        desc->getElapsedTime(), elapsedTimeThruCacheGet, deltaPercent);
+            }
+            if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) {
+                dumpCacheStats();
+            }
+        }
+    }
+}
+
+void TextLayoutCache::dumpCacheStats() {
+    float remainingPercent = 100 * ((mMaxSize - mSize) / ((float)mMaxSize));
+    float timeRunningInSec = (systemTime(SYSTEM_TIME_MONOTONIC) - mCacheStartTime) / 1000000000;
+    LOGD("------------------------------------------------");
+    LOGD("TextLayoutCache stats");
+    LOGD("------------------------------------------------");
+    LOGD("running   : %.0f seconds", timeRunningInSec);
+    LOGD("size      : %d bytes", mMaxSize);
+    LOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
+    LOGD("hits      : %d", mCacheHitCount);
+    LOGD("saved     : %lld milliseconds", mNanosecondsSaved / 1000000);
+    LOGD("------------------------------------------------");
+}
+
+} // namespace android
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
new file mode 100644
index 0000000..9d55918
--- /dev/null
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -0,0 +1,314 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_TEXT_LAYOUT_CACHE_H
+#define ANDROID_TEXT_LAYOUT_CACHE_H
+
+#include "RtlProperties.h"
+
+#include "stddef.h"
+#include <utils/threads.h>
+#include <utils/String16.h>
+#include "utils/GenerationCache.h"
+#include "utils/Compare.h"
+
+#include "SkPaint.h"
+#include "SkTemplates.h"
+
+#include "unicode/ubidi.h"
+#include "unicode/ushape.h"
+
+#include <android_runtime/AndroidRuntime.h>
+
+#define UNICODE_NOT_A_CHAR              0xffff
+#define UNICODE_ZWSP                    0x200b
+#define UNICODE_FIRST_LOW_SURROGATE     0xdc00
+#define UNICODE_FIRST_HIGH_SURROGATE    0xd800
+#define UNICODE_FIRST_PRIVATE_USE       0xe000
+#define UNICODE_FIRST_RTL_CHAR          0x0590
+
+// Temporary buffer size
+#define CHAR_BUFFER_SIZE 80
+
+// Converts a number of mega-bytes into bytes
+#define MB(s) s * 1024 * 1024
+
+// Define the default cache size in Mb
+#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.125f
+
+// Define the interval in number of cache hits between two statistics dump
+#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
+
+namespace android {
+
+/**
+ * TextLayoutCacheKey is the Cache key
+ */
+class TextLayoutCacheKey {
+public:
+    TextLayoutCacheKey() : text(NULL), start(0), count(0), contextCount(0),
+            dirFlags(0), textSize(0), typeface(NULL), textSkewX(0), fakeBoldText(false)  {
+    }
+
+    TextLayoutCacheKey(const SkPaint* paint,
+            const UChar* text, size_t start, size_t count,
+            size_t contextCount, int dirFlags) :
+                text(text), start(start), count(count), contextCount(contextCount),
+                dirFlags(dirFlags) {
+        textSize = paint->getTextSize();
+        typeface = paint->getTypeface();
+        textSkewX = paint->getTextSkewX();
+        fakeBoldText = paint->isFakeBoldText();
+    }
+
+    bool operator<(const TextLayoutCacheKey& rhs) const {
+        LTE_INT(count) {
+            LTE_INT(contextCount) {
+                LTE_INT(start) {
+                    LTE_FLOAT(textSize) {
+                        LTE_INT(typeface) {
+                            LTE_INT(textSkewX) {
+                                LTE_INT(fakeBoldText) {
+                                    LTE_INT(dirFlags) {
+                                        return strncmp16(text, rhs.text, contextCount) < 0;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    // We need to copy the text when we insert the key into the cache itself.
+    // We don't need to copy the text when we are only comparing keys.
+    void internalTextCopy() {
+        textCopy.setTo(text, contextCount);
+        text = textCopy.string();
+    }
+
+    /**
+     * Get the size of the Cache key.
+     */
+    size_t getSize() {
+        return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount;
+    }
+
+private:
+    const UChar* text;
+    String16 textCopy;
+    size_t start;
+    size_t count;
+    size_t contextCount;
+    int dirFlags;
+    float textSize;
+    SkTypeface* typeface;
+    float textSkewX;
+    bool fakeBoldText;
+}; // TextLayoutCacheKey
+
+/*
+ * RunAdvanceDescription is the Cache entry
+ */
+class RunAdvanceDescription {
+public:
+    RunAdvanceDescription() {
+        advances = NULL;
+        totalAdvance = 0;
+    }
+
+    ~RunAdvanceDescription() {
+        delete[] advances;
+    }
+
+    void setElapsedTime(uint32_t time) {
+        elapsedTime = time;
+    }
+
+    uint32_t getElapsedTime() {
+        return elapsedTime;
+    }
+
+    void computeAdvances(SkPaint* paint, const UChar* chars, size_t start, size_t count,
+            size_t contextCount, int dirFlags) {
+        advances = new float[count];
+        this->count = count;
+
+        computeAdvances(paint, chars, start, count, contextCount, dirFlags,
+                advances, &totalAdvance);
+    }
+
+    void copyResult(jfloat* outAdvances, jfloat* outTotalAdvance) {
+        memcpy(outAdvances, advances, count * sizeof(jfloat));
+        *outTotalAdvance = totalAdvance;
+    }
+
+    /**
+     * Get the size of the Cache entry
+     */
+    size_t getSize() {
+        return sizeof(RunAdvanceDescription) + sizeof(jfloat) * count;
+    }
+
+    static void computeAdvances(SkPaint* paint, const UChar* chars, size_t start, size_t count,
+            size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) {
+        SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
+        jchar* buffer = tempBuffer.get();
+
+        SkScalar* scalarArray = (SkScalar*)outAdvances;
+
+        // this is where we'd call harfbuzz
+        // for now we just use ushape.c
+        size_t widths;
+        const jchar* text;
+        if (dirFlags & 0x1) { // rtl, call arabic shaping in case
+            UErrorCode status = U_ZERO_ERROR;
+            // Use fixed length since we need to keep start and count valid
+            u_shapeArabic(chars, contextCount, buffer, contextCount,
+                    U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
+                    U_SHAPE_TEXT_DIRECTION_LOGICAL | U_SHAPE_LETTERS_SHAPE |
+                    U_SHAPE_X_LAMALEF_SUB_ALTERNATE, &status);
+            // we shouldn't fail unless there's an out of memory condition,
+            // in which case we're hosed anyway
+            for (int i = start, e = i + count; i < e; ++i) {
+                if (buffer[i] == UNICODE_NOT_A_CHAR) {
+                    buffer[i] = UNICODE_ZWSP; // zero-width-space for skia
+                }
+            }
+            text = buffer + start;
+            widths = paint->getTextWidths(text, count << 1, scalarArray);
+        } else {
+            text = chars + start;
+            widths = paint->getTextWidths(text, count << 1, scalarArray);
+        }
+
+        jfloat totalAdvance = 0;
+        if (widths < count) {
+            // Skia operates on code points, not code units, so surrogate pairs return only
+            // one value. Expand the result so we have one value per UTF-16 code unit.
+
+            // Note, skia's getTextWidth gets confused if it encounters a surrogate pair,
+            // leaving the remaining widths zero.  Not nice.
+            for (size_t i = 0, p = 0; i < widths; ++i) {
+                totalAdvance += outAdvances[p++] = SkScalarToFloat(scalarArray[i]);
+                if (p < count &&
+                        text[p] >= UNICODE_FIRST_LOW_SURROGATE &&
+                        text[p] < UNICODE_FIRST_PRIVATE_USE &&
+                        text[p-1] >= UNICODE_FIRST_HIGH_SURROGATE &&
+                        text[p-1] < UNICODE_FIRST_LOW_SURROGATE) {
+                    outAdvances[p++] = 0;
+                }
+            }
+        } else {
+            for (size_t i = 0; i < count; i++) {
+                totalAdvance += outAdvances[i] = SkScalarToFloat(scalarArray[i]);
+            }
+        }
+        *outTotalAdvance = totalAdvance;
+    }
+
+private:
+    jfloat* advances;
+    jfloat totalAdvance;
+    size_t count;
+
+    uint32_t elapsedTime;
+}; // RunAdvanceDescription
+
+
+class TextLayoutCache: public OnEntryRemoved<TextLayoutCacheKey, RunAdvanceDescription*>
+{
+public:
+    TextLayoutCache();
+    TextLayoutCache(uint32_t maxByteSize);
+
+    virtual ~TextLayoutCache();
+
+    bool isInitialized() {
+        return mInitialized;
+    }
+
+    /**
+     * Used as a callback when an entry is removed from the cache.
+     * Do not invoke directly.
+     */
+    void operator()(TextLayoutCacheKey& text, RunAdvanceDescription*& desc);
+
+    /**
+     * Get cache entries
+     */
+    void getRunAdvances(SkPaint* paint, const jchar* text,
+            jint start, jint count, jint contextCount, jint dirFlags,
+            jfloat* outAdvances, jfloat* outTotalAdvance);
+
+    /**
+     * Clear the cache
+     */
+    void clear();
+
+    /**
+     * Sets the maximum size of the cache in bytes.
+     */
+    void setMaxSize(uint32_t maxSize);
+
+    /**
+     * Returns the maximum size of the cache in bytes.
+     */
+    uint32_t getMaxSize();
+
+    /**
+     * Returns the current size of the cache in bytes.
+     */
+    uint32_t getSize();
+
+private:
+    Mutex mLock;
+    bool mInitialized;
+
+    GenerationCache<TextLayoutCacheKey, RunAdvanceDescription*> mCache;
+
+    uint32_t mSize;
+    uint32_t mMaxSize;
+
+    uint32_t mCacheHitCount;
+    uint64_t mNanosecondsSaved;
+
+    uint64_t mCacheStartTime;
+
+    RtlDebugLevel mDebugLevel;
+    bool mDebugEnabled;
+
+    /*
+     * Class initialization
+     */
+    void init();
+
+    /**
+     * Remove oldest entries until we are having enough space
+     */
+    void removeOldests();
+
+    /**
+     * Dump Cache statistics
+     */
+    void dumpCacheStats();
+}; // TextLayoutCache
+
+} // namespace android
+#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
+
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 56f2646..b1ea90b 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -42,8 +42,6 @@
 {
 
 static struct {
-    jclass clazz;
-
     jmethodID dispatchUnhandledKeyEvent;
     jmethodID preDispatchKeyEvent;
     jmethodID finish;
@@ -1054,8 +1052,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class %s", className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class %s", className);
 
 #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
         var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
@@ -1064,30 +1061,30 @@
 int register_android_app_NativeActivity(JNIEnv* env)
 {
     //LOGD("register_android_app_NativeActivity");
+    jclass clazz;
+    FIND_CLASS(clazz, kNativeActivityPathName);
 
-    FIND_CLASS(gNativeActivityClassInfo.clazz, kNativeActivityPathName);
-    
     GET_METHOD_ID(gNativeActivityClassInfo.dispatchUnhandledKeyEvent,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "dispatchUnhandledKeyEvent", "(Landroid/view/KeyEvent;)Z");
     GET_METHOD_ID(gNativeActivityClassInfo.preDispatchKeyEvent,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "preDispatchKeyEvent", "(Landroid/view/KeyEvent;I)V");
 
     GET_METHOD_ID(gNativeActivityClassInfo.finish,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "finish", "()V");
     GET_METHOD_ID(gNativeActivityClassInfo.setWindowFlags,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "setWindowFlags", "(II)V");
     GET_METHOD_ID(gNativeActivityClassInfo.setWindowFormat,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "setWindowFormat", "(I)V");
     GET_METHOD_ID(gNativeActivityClassInfo.showIme,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "showIme", "(I)V");
     GET_METHOD_ID(gNativeActivityClassInfo.hideIme,
-            gNativeActivityClassInfo.clazz,
+            clazz,
             "hideIme", "(I)V");
 
     return AndroidRuntime::registerNativeMethods(
diff --git a/core/jni/android_content_res_Configuration.cpp b/core/jni/android_content_res_Configuration.cpp
index 28a43ab..95b18ea 100644
--- a/core/jni/android_content_res_Configuration.cpp
+++ b/core/jni/android_content_res_Configuration.cpp
@@ -26,8 +26,6 @@
 namespace android {
 
 static struct {
-    jclass clazz;
-
     jfieldID mcc;
     jfieldID mnc;
     jfieldID locale;
@@ -75,8 +73,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
@@ -84,31 +81,32 @@
 
 int register_android_content_res_Configuration(JNIEnv* env)
 {
-    FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration");
+    jclass clazz;
+    FIND_CLASS(clazz, "android/content/res/Configuration");
 
-    GET_FIELD_ID(gConfigurationClassInfo.mcc, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.mcc, clazz,
             "mcc", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.mnc, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.mnc, clazz,
             "mnc", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.locale, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.locale, clazz,
             "locale", "Ljava/util/Locale;");
-    GET_FIELD_ID(gConfigurationClassInfo.screenLayout, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.screenLayout, clazz,
             "screenLayout", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.touchscreen, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.touchscreen, clazz,
             "touchscreen", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.keyboard, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.keyboard, clazz,
             "keyboard", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.keyboardHidden, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.keyboardHidden, clazz,
             "keyboardHidden", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.hardKeyboardHidden, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.hardKeyboardHidden, clazz,
             "hardKeyboardHidden", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.navigation, clazz,
             "navigation", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.navigationHidden, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.navigationHidden, clazz,
             "navigationHidden", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.orientation, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.orientation, clazz,
             "orientation", "I");
-    GET_FIELD_ID(gConfigurationClassInfo.uiMode, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.uiMode, clazz,
             "uiMode", "I");
 
     return AndroidRuntime::registerNativeMethods(env, "android/content/res/Configuration", gMethods,
diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp
index 3fd7985..4759e27 100644
--- a/core/jni/android_content_res_ObbScanner.cpp
+++ b/core/jni/android_content_res_ObbScanner.cpp
@@ -91,8 +91,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
@@ -100,15 +99,16 @@
 
 int register_android_content_res_ObbScanner(JNIEnv* env)
 {
-    FIND_CLASS(gObbInfoClassInfo.clazz, "android/content/res/ObbInfo");
+    jclass clazz;
+    FIND_CLASS(clazz, "android/content/res/ObbInfo");
 
-    GET_FIELD_ID(gObbInfoClassInfo.packageName, gObbInfoClassInfo.clazz,
+    GET_FIELD_ID(gObbInfoClassInfo.packageName, clazz,
             "packageName", "Ljava/lang/String;");
-    GET_FIELD_ID(gObbInfoClassInfo.version, gObbInfoClassInfo.clazz,
+    GET_FIELD_ID(gObbInfoClassInfo.version, clazz,
             "version", "I");
-    GET_FIELD_ID(gObbInfoClassInfo.flags, gObbInfoClassInfo.clazz,
+    GET_FIELD_ID(gObbInfoClassInfo.flags, clazz,
             "flags", "I");
-    GET_FIELD_ID(gObbInfoClassInfo.salt, gObbInfoClassInfo.clazz,
+    GET_FIELD_ID(gObbInfoClassInfo.salt, clazz,
             "salt", "[B");
 
     return AndroidRuntime::registerNativeMethods(env, "android/content/res/ObbScanner", gMethods,
@@ -116,4 +116,3 @@
 }
 
 }; // namespace android
-
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index d8a3db3..2b4a955 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -36,7 +36,6 @@
 
 namespace android {
 
-static jclass gFileStatusClass;
 static jfieldID gFileStatusDevFieldID;
 static jfieldID gFileStatusInoFieldID;
 static jfieldID gFileStatusModeFieldID;
@@ -189,21 +188,21 @@
     clazz = env->FindClass(kFileUtilsPathName);
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.FileUtils");
     
-    gFileStatusClass = env->FindClass("android/os/FileUtils$FileStatus");
-    LOG_FATAL_IF(gFileStatusClass == NULL, "Unable to find class android.os.FileUtils$FileStatus");
+    jclass fileStatusClass = env->FindClass("android/os/FileUtils$FileStatus");
+    LOG_FATAL_IF(fileStatusClass == NULL, "Unable to find class android.os.FileUtils$FileStatus");
 
-    gFileStatusDevFieldID = env->GetFieldID(gFileStatusClass, "dev", "I");
-    gFileStatusInoFieldID = env->GetFieldID(gFileStatusClass, "ino", "I");
-    gFileStatusModeFieldID = env->GetFieldID(gFileStatusClass, "mode", "I");
-    gFileStatusNlinkFieldID = env->GetFieldID(gFileStatusClass, "nlink", "I");
-    gFileStatusUidFieldID = env->GetFieldID(gFileStatusClass, "uid", "I");
-    gFileStatusGidFieldID = env->GetFieldID(gFileStatusClass, "gid", "I");
-    gFileStatusSizeFieldID = env->GetFieldID(gFileStatusClass, "size", "J");
-    gFileStatusBlksizeFieldID = env->GetFieldID(gFileStatusClass, "blksize", "I");
-    gFileStatusBlocksFieldID = env->GetFieldID(gFileStatusClass, "blocks", "J");
-    gFileStatusAtimeFieldID = env->GetFieldID(gFileStatusClass, "atime", "J");
-    gFileStatusMtimeFieldID = env->GetFieldID(gFileStatusClass, "mtime", "J");
-    gFileStatusCtimeFieldID = env->GetFieldID(gFileStatusClass, "ctime", "J");
+    gFileStatusDevFieldID = env->GetFieldID(fileStatusClass, "dev", "I");
+    gFileStatusInoFieldID = env->GetFieldID(fileStatusClass, "ino", "I");
+    gFileStatusModeFieldID = env->GetFieldID(fileStatusClass, "mode", "I");
+    gFileStatusNlinkFieldID = env->GetFieldID(fileStatusClass, "nlink", "I");
+    gFileStatusUidFieldID = env->GetFieldID(fileStatusClass, "uid", "I");
+    gFileStatusGidFieldID = env->GetFieldID(fileStatusClass, "gid", "I");
+    gFileStatusSizeFieldID = env->GetFieldID(fileStatusClass, "size", "J");
+    gFileStatusBlksizeFieldID = env->GetFieldID(fileStatusClass, "blksize", "I");
+    gFileStatusBlocksFieldID = env->GetFieldID(fileStatusClass, "blocks", "J");
+    gFileStatusAtimeFieldID = env->GetFieldID(fileStatusClass, "atime", "J");
+    gFileStatusMtimeFieldID = env->GetFieldID(fileStatusClass, "mtime", "J");
+    gFileStatusCtimeFieldID = env->GetFieldID(fileStatusClass, "ctime", "J");
 
     return AndroidRuntime::registerNativeMethods(
         env, kFileUtilsPathName,
diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp
index d2e5462..12a77d5 100644
--- a/core/jni/android_os_MessageQueue.cpp
+++ b/core/jni/android_os_MessageQueue.cpp
@@ -27,8 +27,6 @@
 // ----------------------------------------------------------------------------
 
 static struct {
-    jclass clazz;
-
     jfieldID mPtr;   // native object attached to the DVM MessageQueue
 } gMessageQueueClassInfo;
 
@@ -135,8 +133,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
@@ -147,9 +144,10 @@
             gMessageQueueMethods, NELEM(gMessageQueueMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
-    FIND_CLASS(gMessageQueueClassInfo.clazz, "android/os/MessageQueue");
+    jclass clazz;
+    FIND_CLASS(clazz, "android/os/MessageQueue");
 
-    GET_FIELD_ID(gMessageQueueClassInfo.mPtr, gMessageQueueClassInfo.clazz,
+    GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz,
             "mPtr", "I");
     
     return 0;
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 1bce332..fdb7fda 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1806,7 +1806,9 @@
         = env->GetFieldID(assetManager, "mObject", "I");
     LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
 
-    g_stringClass = env->FindClass("java/lang/String");
+    jclass stringClass = env->FindClass("java/lang/String");
+    LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
+    g_stringClass = (jclass)env->NewGlobalRef(stringClass);
 
     return AndroidRuntime::registerNativeMethods(env,
             "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index a78f660..26c915f 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -70,7 +70,6 @@
 // ----------------------------------------------------------------------------
 
 static struct {
-    jclass clazz;
     jmethodID set;
 } gRectClassInfo;
 
@@ -683,9 +682,8 @@
 #ifdef USE_OPENGL_RENDERER
     #define FIND_CLASS(var, className) \
             var = env->FindClass(className); \
-            LOG_FATAL_IF(! var, "Unable to find class " className); \
-            var = jclass(env->NewGlobalRef(var));
-    
+            LOG_FATAL_IF(! var, "Unable to find class " className);
+
     #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
             var = env->GetMethodID(clazz, methodName, methodDescriptor); \
             LOG_FATAL_IF(! var, "Unable to find method " methodName);
@@ -695,8 +693,9 @@
 #endif
 
 int register_android_view_GLES20Canvas(JNIEnv* env) {
-    FIND_CLASS(gRectClassInfo.clazz, "android/graphics/Rect");
-    GET_METHOD_ID(gRectClassInfo.set, gRectClassInfo.clazz, "set", "(IIII)V");
+    jclass clazz;
+    FIND_CLASS(clazz, "android/graphics/Rect");
+    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
 
     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index bfeec4f..aba3a72 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -30,8 +30,6 @@
 } gKeyEventClassInfo;
 
 static struct {
-    jclass clazz;
-
     jfieldID keyCode;
     jfieldID metaState;
 } gFallbackActionClassInfo;
@@ -165,8 +163,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
@@ -175,13 +172,15 @@
 int register_android_text_KeyCharacterMap(JNIEnv* env)
 {
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
+    gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
 
-    FIND_CLASS(gFallbackActionClassInfo.clazz, "android/view/KeyCharacterMap$FallbackAction");
+    jclass clazz;
+    FIND_CLASS(clazz, "android/view/KeyCharacterMap$FallbackAction");
 
-    GET_FIELD_ID(gFallbackActionClassInfo.keyCode, gFallbackActionClassInfo.clazz,
+    GET_FIELD_ID(gFallbackActionClassInfo.keyCode, clazz,
             "keyCode", "I");
 
-    GET_FIELD_ID(gFallbackActionClassInfo.metaState, gFallbackActionClassInfo.clazz,
+    GET_FIELD_ID(gFallbackActionClassInfo.metaState, clazz,
             "metaState", "I");
 
     return AndroidRuntime::registerNativeMethods(env,
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 97cba23..68ebfe7 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -42,8 +42,6 @@
 } gMotionEventClassInfo;
 
 static struct {
-    jclass clazz;
-
     jfieldID mPackedAxisBits;
     jfieldID mPackedAxisValues;
     jfieldID x;
@@ -734,8 +732,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
         var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
@@ -755,6 +752,7 @@
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
+    gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
 
     GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz,
             "obtain", "()Landroid/view/MotionEvent;");
@@ -763,29 +761,30 @@
     GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz,
             "mNativePtr", "I");
 
-    FIND_CLASS(gPointerCoordsClassInfo.clazz, "android/view/MotionEvent$PointerCoords");
+    jclass clazz;
+    FIND_CLASS(clazz, "android/view/MotionEvent$PointerCoords");
 
-    GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, clazz,
             "mPackedAxisBits", "J");
-    GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, clazz,
             "mPackedAxisValues", "[F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.x, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.x, clazz,
             "x", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.y, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.y, clazz,
             "y", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.pressure, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.pressure, clazz,
             "pressure", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.size, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.size, clazz,
             "size", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, clazz,
             "touchMajor", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, clazz,
             "touchMinor", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, clazz,
             "toolMajor", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, clazz,
             "toolMinor", "F");
-    GET_FIELD_ID(gPointerCoordsClassInfo.orientation, gPointerCoordsClassInfo.clazz,
+    GET_FIELD_ID(gPointerCoordsClassInfo.orientation, clazz,
             "orientation", "F");
 
     return 0;
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index bd2e669..9f1b1fd 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -378,7 +378,7 @@
         JNIEnv* env, jobject clazz, jobject argCanvas)
 {
     jobject canvas = env->GetObjectField(clazz, so.canvas);
-    if (canvas != argCanvas) {
+    if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) {
         doThrow(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index e9261d9..6d1f1aa 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"للسماح للتطبيق بالتحكم في الهزاز."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"التحكم في الضوء الوامض"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"للسماح للتطبيق بالتحكم في الضوء الوامض."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"الدخول إلى أجهزة USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"للسماح للتطبيق بالدخول إلى أجهزة USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"تنفيذ بروتوكول MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"لإتاحة الدخول إلى برنامج تشغيل kernel MTP لتنفيذ بروتوكول MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"اختبار الأجهزة"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"محو بيانات الهاتف بدون تحذير، وذلك عبر إجراء إعادة الضبط بحسب بيانات المصنع"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تعيين الخادم الوكيل العمومي للجهاز"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"تعيين الخادم الوكيل العمومي للجهاز لكي يتم استخدامه أثناء تمكين السياسة. يعين مشرف الجهاز الأول فقط الخادم الوكيل العمومي الفعال."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"ضبط انتهاء كلمة مرور تأمين شاشة"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"التحكم في عدد مرات تغيير كلمة مرور تأمين الشاشة"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"تعيين انتهاء صلاحية كلمة المرور"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"التحكم في الوقت المستغرق قبل الحاجة إلى تغيير كلمة مرور شاشة التوقف"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تعيين تشفير التخزين"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"طلب تشفير بيانات التطبيق المخزنة"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"الاستخدام بشكل افتراضي لهذا الإجراء."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"محو الإعداد الافتراضي في الإعدادات الرئيسية &gt; التطبيقات &gt; إدارة التطبيقات."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"تحديد إجراء"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"ليس هناك تطبيقات يمكنها تنفيذ هذا الإجراء."</string>
     <string name="aerr_title" msgid="653922989522758100">"عذرًا!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"توقف التطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> (العملية <xliff:g id="PROCESS">%2$s</xliff:g>) على نحو غير متوقع. الرجاء المحاولة مرة أخرى."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index d15baa9..ca36b5c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Разрешава на приложението да контролира устройството за вибрация."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"контролиране на фенерчето"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Разрешава на приложението да контролира фенерчето."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"достъп до USB устройства"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Разрешава на приложението достъп до USB устройства."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"внедряване на MTP протокол"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Разрешава достъп до MTP драйвера на ядрото за внедряване на протокола MTP през USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"тест на хардуера"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Изтриване на данните в телефона без предупреждение чрез възстановяване на фабричните настройки"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Задаване на глобален прокси сървър за устройството"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Задаване на глобалния прокси сървър, който да се използва, когато правилото е активирано. Само първият администратор на устройството задава действителния глобален прокси сървър."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Изтичане на паролата"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролирайте колко често трябва да се променя паролата за заключен екран"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Задаване на срок на валидност на паролата"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролирайте след колко време трябва да се променя паролата за заключване на екрана"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Шифроване за хранилището"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Изисква съхраняваните данни за приложенията да бъдат шифровани"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Използване по подразбиране за това действие."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Изчистване на стандартната стойност в „Начални настройки“ &gt; „Приложения“ &gt; „Управление на приложенията“."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Избиране на действие"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Това действие не може да се изпълни от нито едно приложение."</string>
     <string name="aerr_title" msgid="653922989522758100">"Съжаляваме!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Приложението „<xliff:g id="APPLICATION">%1$s</xliff:g>“ (процес „<xliff:g id="PROCESS">%2$s</xliff:g>“) спря неочаквано. Моля, опитайте отново."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 263f1c4..d506c67 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permet a l\'aplicació controlar el vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar el flaix"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permet a l\'aplicació controlar el flaix."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"accedeix a dispositius USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permet que l\'aplicació accedeixi als dispositius USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementa el protocol MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permet l\'accés al programa de control MTP de kernel per implementar el protocol USB d\'MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"provar el maquinari"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Esborra les dades del telèfon sense advertiment mitjançant un restabliment de les dades de fàbrica"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Defineix el servidor intermediari global del dispositiu"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Defineix el servidor intermediari global del dispositiu que cal utilitzar mentre la política estigui activada. Només el primer administrador del dispositiu pot definir el servidor intermediari global efectiu."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Defineix la caducitat de la contrasenya de bloqueig de pantalla"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controla la freqüència amb què cal canviar la contrasenya de bloqueig de pantalla"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Defineix la caducitat de la contrasenya"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controla quant de temps abans de la pantalla de bloqueig cal canviar la contrasenya"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utilitza-ho de manera predeterminada per a aquesta acció."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Esborra el valor predeterminat a Configuració de la pantalla d\'inici &gt; Aplicacions &gt; Gestiona les aplicacions."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Seleccioneu una acció"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"No hi ha cap aplicació que pugui dur a terme aquesta acció."</string>
     <string name="aerr_title" msgid="653922989522758100">"Ho sentim."</string>
     <string name="aerr_application" msgid="4683614104336409186">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> (procés <xliff:g id="PROCESS">%2$s</xliff:g>) s\'ha aturat inesperadament. Torneu-ho a provar."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b93989f..afc8a2e 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Umožňuje aplikaci ovládat vibrace."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ovládání kontrolky"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Umožňuje aplikaci ovládat kontrolku."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"přístup k zařízením USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Umožní aplikaci přístup k zařízením USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementace protokolu MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Povoluje přístup k ovladači protokolu MTP jádra za účelem implementace protokolu MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testování hardwaru"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Bez upozornění smazat všechna data telefonu obnovením továrních dat"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastavit globální proxy server zařízení"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globální proxy server, který se bude používat, když jsou zásady aktivní. Aktuální globální proxy server nastavuje pouze první správce zařízení."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavit vypršení hesla zámku"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Určuje, jak často je třeba měnit heslo pro uzamčení obrazovky"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavit konec platnosti hesla"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ovládání doby, po jejímž uplynutí je nutné změnit heslo pro odemknutí obrazovky"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavit šifrování úložiště"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Požadovat šifrování ukládaných dat"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Použít jako výchozí nastavení pro tuto činnost."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Vymažte výchozí hodnoty v Nastavení plochy &gt; Aplikace &gt; Správa aplikací."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Vyberte akci"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Tuto činnost nemohou provádět žádné aplikace."</string>
     <string name="aerr_title" msgid="653922989522758100">"Omlouváme se"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) byla neočekávaně ukončena. Zkuste to znovu."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 25246f6..3e283fc 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Lader programmet kontrollere vibratoren."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontroller lommelygte"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Tillader, at programmet kontrollerer lommelygten."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"adgang til USB-enheder."</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Tillader, at programmet har adgang til USB-enheder."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementere MTP-protokol"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Tillader adgang til kerne-MTP-driveren for at implementere MTB USB-protokollen."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"test hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Slet telefonens data uden varsel ved at gendanne fabriksindstillinger"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angiv enhedens globale proxy"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Angiv enhedens globale proxy, der skal bruges, mens politikken er aktiveret. Kun den første enhedsadministrator angiver den effektive globale proxy."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Angiv udløb for skærmlåskoden"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Administrer, hvor tit skærmlåsens adgangskode skal skiftes"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Angiv udløb for adgangskode"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontroller, hvor lang tid der skal gå, før adgangskoden til skærmlåsen skal ændres."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angiv kryptering af lager"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kræv, at gemte programdata krypteres"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Brug som standard til denne handling."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Ryd standard i Startindstillinger &gt; Programmer &gt; Administrer programmer."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Vælg en handling"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Der er ingen programmer, der kan foretage denne handling."</string>
     <string name="aerr_title" msgid="653922989522758100">"Beklager!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) er standset uventet. Prøv igen."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 08f29ba..ccee3d0 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -49,7 +49,7 @@
     <string name="needPuk" msgid="919668385956251611">"Ihre SIM-Karte ist mit einem PUK gesperrt. Geben Sie zum Entsperren den PUK-Code ein."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Geben Sie zum Entsperren der SIM-Karte den PUK2 ein."</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Anrufer-ID für eingehenden Anruf"</string>
-    <string name="ClirMmi" msgid="7784673673446833091">"Anrufer-ID für ausgehenden Anruf"</string>
+    <string name="ClirMmi" msgid="7784673673446833091">"Anrufer-ID für abgehenden Anruf"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Rufweiterleitung"</string>
     <string name="CwMmi" msgid="9129678056795016867">"Anklopfen"</string>
     <string name="BaMmi" msgid="455193067926770581">"Anrufsperre"</string>
@@ -153,14 +153,14 @@
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
     <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
-    <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
+    <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
     <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Ermöglicht Anwendungen die Ausführung eventuell kostenpflichtiger Aktionen."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Ihre Nachrichten"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Lesen und schreiben Sie Ihre SMS, E-Mails und anderen Nachrichten."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Ihre persönlichen Informationen"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Tablets"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Telefons"</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Tablets."</string>
+    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkter Zugriff auf die Kontakte und den Kalender Ihres Telefons."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Ihren Standort"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Ihren physischen Standort überwachen"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Netzwerkkommunikation"</string>
@@ -177,14 +177,14 @@
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funktionen nur für Anwendungsentwickler vorgesehen."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Speicher"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Zugriff auf USB-Speicher"</string>
-    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Zugriff auf SD-Karte"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Greift auf die SD-Karte zu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Ermöglicht der Anwendung, die Statusanzeige zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"Statusleiste"</string>
     <string name="permdesc_statusBarService" msgid="4097605867643520920">"Ermöglicht der Anwendung, zur Statusleiste zu werden."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"Statusleiste ein-/ausblenden"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Ermöglicht der Anwendung, die Statusleiste ein- oder auszublenden."</string>
-    <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"Ausgehende Anrufe abfangen"</string>
+    <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"Abgehende Anrufe abfangen"</string>
     <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Ermöglicht einer Anwendung, abgehende Anrufe zu verarbeiten und die zu wählende Nummer zu ändern. Schädliche Anwendungen können so abgehende Anrufe eventuell überwachen, umleiten oder verhindern."</string>
     <string name="permlab_receiveSms" msgid="2697628268086208535">"SMS empfangen"</string>
     <string name="permdesc_receiveSms" msgid="6298292335965966117">"Ermöglicht der Anwendung, Kurzmitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
@@ -241,7 +241,7 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"nicht autorisierte Fenster anzeigen"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ermöglicht die Erstellung von Fenstern, die von der Benutzeroberfläche des internen Systems verwendet werden. Nicht für normale Anwendungen geeignet."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"Warnungen auf Systemebene anzeigen"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ermöglicht einer Anwendung, Fenster mit Systemwarnungen anzuzeigen. Schädliche Anwendungen können so die Kontrolle über das gesamte Display übernehmen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ermöglicht einer Anwendung, Fenster mit Systemwarnungen anzuzeigen. Schädliche Anwendungen können so das gesamte Display einnehmen."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"Allgemeine Animationsgeschwindigkeit einstellen"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ermöglicht einer Anwendung, die allgemeine Animationsgeschwindigkeit (schnellere oder langsamere Animationen) jederzeit anzupassen."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"Anwendungs-Tokens verwalten"</string>
@@ -279,7 +279,7 @@
     <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ermöglicht einer Anwendung, Tablet-Speicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ermöglicht einer Anwendung, Telefonspeicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Anwendungsressourcen verschieben"</string>
-    <string name="permdesc_movePackage" msgid="6323049291923925277">"Ermöglicht einer Anwendung, Anwendungsressourcen von internen auf externe Medien zu verschieben und umgekehrt."</string>
+    <string name="permdesc_movePackage" msgid="6323049291923925277">"Ermöglicht einer Anwendung, Anwendungsressourcen von interne auf externe Medien zu verschieben und umgekehrt."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"Lesen vertraulicher Protokolldaten"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ermöglicht einer Anwendung, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Tablet durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ermöglicht einer Anwendung, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
@@ -300,8 +300,8 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ermöglicht einer Anwendung, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Tablet gestartet wird, und durch die ständige Aktivität der Anwendung wird die gesamte Leistung des Tablets beeinträchtigt."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ermöglicht einer Anwendung, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Telefon gestartet wird, und durch die ständige Aktivität der Anwendung wird die gesamte Leistung des Telefons beeinträchtigt."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"dauerhaften Broadcast senden"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ermöglicht einer Anwendung, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Tablet langsam oder instabil machen, da zu viel Speicherplatz belegt wird."</string>
-    <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ermöglicht einer Anwendung, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Telefon langsam oder unstabil machen, da zuviel Speicherplatz belegt wird."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ermöglicht einer Anwendung, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Tablet langsam oder instabil machen, da zu viel Speicherplatz belegt ist."</string>
+    <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ermöglicht einer Anwendung, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Telefon langsam oder unstabil machen, da zuviel Speicherplatz belegt ist."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"Kontaktdaten lesen"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ermöglicht einer Anwendung, alle auf Ihrem Tablet gespeicherten Kontaktdaten (Adressen) zu lesen. Schädliche Anwendungen können so Ihre Daten an andere Personen senden."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ermöglicht einer Anwendung, alle auf Ihrem Telefon gespeicherten Kontaktdaten (Adressen) zu lesen. Schädliche Anwendungen können so Ihre Daten an andere Personen senden."</string>
@@ -312,8 +312,8 @@
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ermöglicht einer Anwendung, alle auf Ihrem Tablet gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ermöglicht einer Anwendung, alle auf Ihrem Telefon gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"Kalendereinträge hinzufügen oder ändern und E-Mails an Gäste senden"</string>
-    <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ermöglicht einer Anwendung, Einträge in Ihrem Kalender hinzuzufügen oder zu ändern, wodurch E-Mails an Gäste gesendet werden können. Schädliche Anwendungen können so Ihre Kalenderdaten löschen oder verändern oder E-Mails versenden."</string>
-    <string name="permlab_accessMockLocation" msgid="8688334974036823330">"Simulierte Standortquellen für Testzwecke"</string>
+    <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ermöglicht einer Anwendung, Einträge auf Ihrem Kalender hinzuzufügen oder zu ändern, die E-Mails an Gäste senden können. Schädliche Anwendungen können so Ihre Kalenderdaten löschen oder verändern oder E-Mails versenden."</string>
+    <string name="permlab_accessMockLocation" msgid="8688334974036823330">"Falsche Standortquellen für Testzwecke"</string>
     <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Erstellt falsche Standortquellen für Testzwecke. Schädliche Anwendungen können so den von den echten Standortquellen wie GPS oder Netzwerkanbieter zurückgegebenen Standort und/oder Status überschreiben."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"Zugriff auf zusätzliche Dienstanbieterbefehle für Standort. Schädliche Anwendungen könnten so die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
@@ -324,7 +324,7 @@
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Zugriff auf genaue Standortquellen wie GPS auf dem Telefon (falls verfügbar). Schädliche Anwendungen können damit bestimmen, so Sie sich befinden und so Ihren Akku zusätzlich belasten."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"ungefährer (netzwerkbasierter) Standort"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Greift auf Quellen mit ungefähren Standortbestimmungen wie die Datenbank des Mobilfunknetzes zu, um falls möglich den ungefähren Standort des Tablets zu bestimmen. Schädliche Anwendungen können damit herauszufinden, wo Sie sich ungefähr befinden."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Greift auf Quellen mit ungefähren Standortbestimmungen wie die Datenbank des Mobilfunknetzes zu, um falls möglich den ungefähren Standort des Tablets festzustellen. Schädliche Anwendungen können damit herausfinden, wo Sie sich ungefähr befinden"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Greift auf Quellen mit ungefähren Standortbestimmungen wie die Datenbank des Mobilfunknetzwerks zu, um falls möglich den ungefähren Standort des Telefons zu bestimmen. Schädliche Anwendungen können damit herauszufinden, wo Sie sich ungefähr befinden."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"Auf SurfaceFlinger zugreifen"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Ermöglicht einer Anwendung, die systemnahen SurfaceFlinger-Funktionen zu verwenden."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"Frame-Puffer lesen"</string>
@@ -336,7 +336,7 @@
     <string name="permlab_camera" msgid="3616391919559751192">"Bilder und Videos aufnehmen"</string>
     <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der Anwendung, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder aus dem Sichtfeld der Kamera erfassen."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"Tablet dauerhaft deaktivieren"</string>
-    <string name="permlab_brick" product="default" msgid="8337817093326370537">"Telefon dauerhaft deaktivieren"</string>
+    <string name="permlab_brick" product="default" msgid="8337817093326370537">"Telefon dauerhaft deaktivieren."</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ermöglicht der Anwendung, das gesamte Tablet dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Ermöglicht der Anwendung, das gesamte Telefon dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"Tablet-Neustart erzwingen"</string>
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Ermöglicht der Anwendung, den Vibrationsalarm zu steuern."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"Lichtanzeige steuern"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Ermöglicht der Anwendung, die Lichtanzeige zu steuern."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"auf USB-Geräte zugreifen"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Ermöglicht der Anwendung den Zugriff auf USB-Geräte."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"MTP-Protokoll implementieren"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Erlaubt den Zugriff auf den Kernel-MTP-Treiber zur Implementierung des MTP-USB-Protokolls."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"Hardware testen"</string>
@@ -395,8 +393,8 @@
     <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Ermöglicht der Anwendung, das Tablet ein- oder auszuschalten."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Ermöglicht der Anwendung, das Telefon ein- oder auszuschalten."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"In Werkstestmodus ausführen"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Führt einen systemnahen Herstellertest durch, in dessen Rahmen auf die gesamte Tablet-Hardware zugegriffen werden kann. Nur verfügbar, wenn ein Tablet im Herstellertestmodus ausgeführt wird."</string>
-    <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Führt einen systemnahen Herstellertest durch, in dessen Rahmen auf die gesamte Telefon-Hardware zugegriffen werden kann. Nur verfügbar, wenn ein Telefon im Herstellertestmodus ausgeführt wird."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Führt einen systemnahen Herstellertest durch, in dessen Rahmen auf die gesamte Tablet-Hardware zugegriffen werden kann. Nur verfügbar, wenn ein Tablet im Werkstestmodus ausgeführt wird."</string>
+    <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Führt einen systemnahen Herstellertest durch, in dessen Rahmen auf die gesamte Telefonhardware zugegriffen werden kann. Nur verfügbar, wenn ein Telefon im Werkstestmodus ausgeführt wird."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"Hintergrund festlegen"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ermöglicht der Anwendung, den System-Hintergrund festzulegen."</string>
     <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"Größenhinweise für Hintergrund festlegen"</string>
@@ -445,7 +443,7 @@
     <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Tablets einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Telefons einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
-    <string name="permdesc_nfc" msgid="9171401851954407226">"Ermöglicht einer Anwendung die Kommunikation mit Tags für Nahfeldkommunikation, Karten und Lesegeräte"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Ermöglicht einer Anwendung die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Tastensperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ermöglicht einer Anwendung, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. So wird die Tastensperre vom Telefon deaktiviert, wenn ein Anruf eingeht, und nach Beendigung des Anrufs wieder aktiviert."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
@@ -462,7 +460,7 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ermöglicht einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"in nutzerdefiniertes Wörterbuch schreiben"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ermöglicht einer Anwendung, Ihrem Wörterbuch neue Einträge hinzuzufügen."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB-Speicherinhalt ändern/löschen"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB-Speicherinh. ändern/lösch."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD-Karten-Inhalt ändern/löschen"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ermöglicht der Anwendung Schreiben in USB-Speicher"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
@@ -480,14 +478,14 @@
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Passwort zum Entsperren des Displays ändern"</string>
     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Passwort zum Entsperren des Displays ändern"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Display sperren"</string>
-    <string name="policydesc_forceLock" msgid="5696964126226028442">"Festlegen, wie und wann das Display gesperrt wird"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Steuern Sie, wie und wann das Display gesperrt wird."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle Daten löschen"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Tablet ohne Warnung löschen"</string>
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Telefon ohne Warnung löschen"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Den globalen Proxy des Geräts festlegen"</string>
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Den bei aktivierter Richtlinie zu verwendenden globalen Proxy des Geräts festlegen. Nur der erste Geräteadministrator kann den gültigen globalen Proxy festlegen."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Ablauf von Sperr-Passwort festlegen"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Legen Sie fest, wie häufig das Passwort zum Sperren des Bildschirms geändert werden muss."</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Den globalen Proxy des Geräts zur Verwendung während der Aktivierung der Richtlinie festlegen. Nur der erste Geräteadministrator kann den gültigen globalen Proxy festlegen."</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Ablauf des Passworts festlegen"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Zeitraum bis zur Änderung des Passworts für die Bildschirmsperre festlegen"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Speicherverschlüsselung"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Anforderung, dass gespeicherte Anwendungsdaten verschlüsselt werden"</string>
   <string-array name="phoneTypes">
@@ -497,19 +495,19 @@
     <item msgid="1103601433382158155">"Fax (geschäftl.)"</item>
     <item msgid="1735177144948329370">"Fax (privat)"</item>
     <item msgid="603878674477207394">"Pager"</item>
-    <item msgid="1650824275177931637">"Andere"</item>
+    <item msgid="1650824275177931637">"Sonstige"</item>
     <item msgid="9192514806975898961">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="emailAddressTypes">
     <item msgid="8073994352956129127">"Privat"</item>
     <item msgid="7084237356602625604">"Geschäftlich"</item>
-    <item msgid="1112044410659011023">"Andere"</item>
+    <item msgid="1112044410659011023">"Sonstige"</item>
     <item msgid="2374913952870110618">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="postalAddressTypes">
     <item msgid="6880257626740047286">"Privat"</item>
     <item msgid="5629153956045109251">"Geschäftlich"</item>
-    <item msgid="4966604264500343469">"Andere"</item>
+    <item msgid="4966604264500343469">"Sonstige"</item>
     <item msgid="4932682847595299369">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="imAddressTypes">
@@ -520,7 +518,7 @@
   </string-array>
   <string-array name="organizationTypes">
     <item msgid="7546335612189115615">"Geschäftlich"</item>
-    <item msgid="4378074129049520373">"Andere"</item>
+    <item msgid="4378074129049520373">"Sonstige"</item>
     <item msgid="3455047468583965104">"Benutzerdefiniert"</item>
   </string-array>
   <string-array name="imProtocols">
@@ -595,10 +593,10 @@
     <string name="relationTypeMother" msgid="4578571352962758304">"Mutter"</string>
     <string name="relationTypeParent" msgid="4755635567562925226">"Elternteil"</string>
     <string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
-    <string name="relationTypeReferredBy" msgid="101573059844135524">"Empfehlung von"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Weitergeleitet von"</string>
     <string name="relationTypeRelative" msgid="1799819930085610271">"Verwandter"</string>
     <string name="relationTypeSister" msgid="1735983554479076481">"Schwester"</string>
-    <string name="relationTypeSpouse" msgid="394136939428698117">"Ehepartner"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Gatte/Gattin"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Benutzerdefiniert"</string>
     <string name="sipAddressTypeHome" msgid="6093598181069359295">"Privat"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Geschäftlich"</string>
@@ -611,7 +609,7 @@
     <string name="keyguard_label_text" msgid="861796461028298424">"Drücken Sie zum Entsperren die Menütaste und dann auf \"0\"."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Notrufnummer"</string>
     <string name="lockscreen_carrier_default" msgid="8812714795156374435">"(kein Dienst)"</string>
-    <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Display gesperrt"</string>
+    <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Display gesperrt."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Drücken Sie die Menütaste, um das Telefon zu entsperren oder einen Notruf zu tätigen."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Zum Entsperren die Menütaste drücken"</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Muster zum Entsperren zeichnen"</string>
@@ -630,7 +628,7 @@
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Bitte legen Sie eine SIM-Karte ein."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Nur Notrufe"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netzwerk gesperrt"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"PUK-Sperre auf SIM"</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"Weitere Informationen finden Sie in der Bedienungsanleitung oder wenden Sie sich an den Kundendienst."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Bitte PIN-Code eingeben"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM-Karte wird entsperrt..."</string>
@@ -693,7 +691,7 @@
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"Leerzeichen"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"Enter"</string>
     <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"löschen"</string>
-    <string name="search_go" msgid="8298016669822141719">"Suchen"</string>
+    <string name="search_go" msgid="8298016669822141719">"Suche"</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Vor 1 Monat"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vor mehr als 1 Monat"</string>
   <plurals name="num_seconds_ago">
@@ -803,7 +801,7 @@
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Textaktionen"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Geringer Speicher"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Kaum noch Tablet-Speicher frei"</string>
-    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Kaum noch Telefonspeicher frei"</string>
+    <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Kaum noch Telefonspeicher frei."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
@@ -811,13 +809,11 @@
     <string name="dialog_alert_title" msgid="2049658708609043103">"Achtung"</string>
     <string name="loading" msgid="1760724998928255250">"Wird geladen..."</string>
     <string name="capital_on" msgid="1544682755514494298">"EIN"</string>
-    <string name="capital_off" msgid="6815870386972805832">"AUS"</string>
+    <string name="capital_off" msgid="6815870386972805832">"Aus"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Aktion durchführen mit"</string>
-    <string name="alwaysUse" msgid="4583018368000610438">"Standardmäßig für diese Aktion verwenden"</string>
-    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Standardeinstellung zurücksetzen unter \"Einstellungen &gt; Anwendungen &gt; Anwendungen verwalten\""</string>
+    <string name="alwaysUse" msgid="4583018368000610438">"Standardmäßig für diese Aktion verwenden."</string>
+    <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Standardeinstellung zurücksetzen unter \"Einstellungen &gt; Anwendungen &gt; Anwendungen verwalten\"."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Aktion auswählen"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Diese Aktion kann von keiner Anwendung ausgeführt werden."</string>
     <string name="aerr_title" msgid="653922989522758100">"Tut uns leid!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Die Anwendung <xliff:g id="APPLICATION">%1$s</xliff:g> (Prozess <xliff:g id="PROCESS">%2$s</xliff:g>) wurde unerwartet beendet. Versuchen Sie es erneut."</string>
@@ -836,13 +832,13 @@
     <string name="smv_application" msgid="295583804361236288">"Die Anwendung <xliff:g id="APPLICATION">%1$s</xliff:g> (Prozess <xliff:g id="PROCESS">%2$s</xliff:g>) hat gegen ihre selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
     <string name="smv_process" msgid="5120397012047462446">"Der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> hat gegen seine selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> läuft"</string>
-    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Zum Wechseln in die Anwendung auswählen"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Auswählen zum Wechseln in die Anwendung"</string>
     <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Anwendung wechseln?"</string>
     <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Es läuft gerade eine andere Anwendung, die vor dem Start einer neuen beendet werden muss."</string>
     <string name="old_app_action" msgid="493129172238566282">"Zu <xliff:g id="OLD_APP">%1$s</xliff:g> zurückkehren"</string>
-    <string name="old_app_description" msgid="942967900237208466">"Die neue Anwendung nicht starten"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Die neue Anwendung nicht starten."</string>
     <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> starten"</string>
-    <string name="new_app_description" msgid="6830398339826789493">"Anwendung beenden, ohne zu speichern"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Anwendung beenden, ohne zu speichern."</string>
     <string name="sendText" msgid="5132506121645618310">"Aktion für Text auswählen"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Klingeltonlautstärke"</string>
     <string name="volume_music" msgid="5421651157138628171">"Medienlautstärke"</string>
@@ -889,14 +885,14 @@
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-Verbindung"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Zum Kopieren von Dateien zum/vom Computer"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB-Speicher deaktivieren"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"USB-Speicher deaktivieren: auswählen"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Auswählen, um USB-Speicher zu deaktivieren."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-Speicher in Verwendung"</string>
     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie den Android-USB-Speicher von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
-    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Achten Sie vor dem Deaktivieren des USB-Speichers darauf, dass Sie die Android-SD-Karte von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
+    <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Stellen Sie vor dem Deaktivieren des USB-Speichers sicher, dass Sie Ihre Android-SD-Karte von Ihrem Computer getrennt (\"ausgeworfen\") haben."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-Speicher deaktivieren"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Beim Deaktivieren des USB-Speichers ist ein Problem aufgetreten. Überprüfen Sie, ob Sie den USB-Host getrennt haben, und versuchen Sie es erneut."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USB-Speicher aktivieren"</string>
-    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendete Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendeten Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-Vorgang fehlgeschlagen"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-Sp. formatieren"</string>
@@ -905,40 +901,40 @@
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging verbunden"</string>
-    <string name="adb_active_notification_message" msgid="8470296818270110396">"USB-Debugging deaktivieren: auswählen"</string>
+    <string name="adb_active_notification_message" msgid="8470296818270110396">"Auswählen, um USB-Debugging zu deaktivieren."</string>
     <string name="select_input_method" msgid="6865512749462072765">"Eingabemethode auswählen"</string>
     <string name="configure_input_methods" msgid="6324843080254191535">"Eingabemethoden konfigurieren"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"Kandidaten"</u></string>
     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB-Speicher wird vorbereitet."</string>
-    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-Karte wird vorbereitet..."</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-Karte wird vorbereitet"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Suche nach Fehlern"</string>
     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"USB-Speicher leer"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"SD-Karte leer"</string>
     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-Speicher ist leer oder verfügt über ein nicht unterstütztes Dateisystem."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-Karte ist leer oder verfügt über ein nicht unterstütztes Dateisystem."</string>
     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB-Speicher beschädigt"</string>
-    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD-Karte beschädigt"</string>
-    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Der USB-Speicher ist beschädigt. Sie müssen ihn eventuell neu formatieren."</string>
-    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Die SD-Karte ist beschädigt. Sie müssen sie eventuell neu formatieren."</string>
-    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-Speicher unerwartet entfernt"</string>
+    <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beschädigte SD-Karte"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-Speicher ist beschädigt. Sie müssen ihn neu formatieren."</string>
+    <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-Speicher unerw. entfernt"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-Karte unerwartet entfernt"</string>
     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Trennen Sie den USB-Speicher vor dem Entfernen, um Datenverlust zu vermeiden."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden."</string>
-    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-Speicher kann entfernt werden."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-Speicher kann entf. werden"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-Karte kann entfernt werden."</string>
     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Der USB-Speicher kann entfernt werden."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Die SD-Karte kann entfernt werden."</string>
     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-Speicher entfernt"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-Karte entfernt"</string>
     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-Speicher entfernt. Neuen Datenträger einlegen"</string>
-    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-Karte entfernt. Neue Karte einlegen"</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-Karte entfernt. Legen Sie eine neue ein."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Keine passenden Aktivitäten gefunden"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"Nutzungsstatistik der Komponente aktualisieren"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Anwendungen vorgesehen."</string>
-    <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Ermöglicht das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalt. Nicht zum Gebrauch mit normalen Anwendungen."</string>
-    <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Ermöglicht das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalt. Nicht zum Gebrauch mit normalen Anwendungen."</string>
+    <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Ermöglicht das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalt. Keine Verwendung bei normalen Anwendungen."</string>
+    <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Ermöglicht das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalt. Keine Verwendung bei normalen Anwendungen."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Für Zoomeinstellung zweimal berühren"</string>
     <string name="gadget_host_error_inflating" msgid="2613287218853846830">"Fehler beim Vergrößern des Widgets"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Los"</string>
@@ -967,7 +963,7 @@
     <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point-Tunneling-Protokoll"</string>
     <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer-2-Tunneling-Protokoll"</string>
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec-VPN mit vorinstalliertem Schlüssel"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec-VPN mit Zertifikat"</string>
+    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Zertifikat mit vorinstalliertem Schlüssel"</string>
     <string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Keine Datei ausgewählt"</string>
     <string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string>
@@ -980,9 +976,9 @@
     <string name="next_button_label" msgid="1080555104677992408">"Weiter"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"Überspringen"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Hohe Mobildatennutzung"</string>
-    <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Durch Berühren weitere Informationen zur Mobildatennutzung aufrufen"</string>
+    <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Mobildatenlimit überschritten"</string>
-    <string name="throttled_notification_message" msgid="4712369856601275146">"Durch Berühren weitere Informationen zur Mobildatennutzung aufrufen"</string>
+    <string name="throttled_notification_message" msgid="4712369856601275146">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string>
     <string name="no_matches" msgid="8129421908915840737">"Keine Treffer"</string>
     <string name="find_on_page" msgid="1946799233822820384">"Auf Seite suchen"</string>
   <plurals name="matches_found">
@@ -1003,7 +999,7 @@
     <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Der USB-Speicher wird derzeit von einem Computer verwendet."</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"Die SD-Karte wird derzeit von einem Computer verwendet."</string>
     <string name="media_unknown_state" msgid="729192782197290385">"Unbekannter Status des externen Speichermediums"</string>
-    <string name="share" msgid="1778686618230011964">"Weitergeben"</string>
+    <string name="share" msgid="1778686618230011964">"Freigeben"</string>
     <string name="find" msgid="4808270900322985960">"Suchen"</string>
     <string name="websearch" msgid="4337157977400211589">"Websuche"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Standortabfrage von <xliff:g id="NAME">%s</xliff:g>"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8b9a8df..edcb213 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Επιτρέπει στην εφαρμογή τον έλεγχο του δονητή."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"έλεγχος φακού"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Επιτρέπει στην εφαρμογή τον έλεγχο του φακού."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"πρόσβαση σε συσκευές USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Επιτρέπει στην εφαρμογή την πρόσβαση σε συσκευές USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"εφαρμογή πρωτοκόλλου MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Επιτρέπει την πρόσβαση στο πρόγραμμα οδήγησης kernel MTP για την εφαρμογή του πρωτοκόλλου MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"δοκιμή υλικού"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Διαγραφή των δεδομένων του τηλεφώνου χωρίς προειδοποίηση με επαναφορά των εργοστασιακών δεδομένων"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ρύθμιση του γενικού διακομιστή μεσολάβησης της συσκευής"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ορίστε τη χρήση του γενικού διακομιστή μεσολάβησης της συσκευής όταν είναι ενεργοποιημένη η πολιτική. Μόνο ο διαχειριστής της πρώτης συσκευής ορίζει τον ισχύοντα γενικό διακομιστή μεσολάβησης."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Ορισμός λήξης κωδ. κλειδ. οθ."</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Επιλέξτε πόσο συχνά θα πρέπει να αλλάζει ο κωδικός πρόσβασης κλειδώματος οθόνης"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Ορισμός λήξης κωδικού πρόσβασης"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ελέγξτε πόσος χρόνος απομένει προτού πρέπει να αλλάξετε τον κωδικό πρόσβασης κλειδώματος της οθόνης"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ορισμός κρυπτογρ. αποθ. χώρου"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Να απαιτείται η κρυπτογράφηση των αποθηκευμένων δεδομένων εφαρμογής"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Χρήση από προεπιλογή για αυτήν την ενέργεια."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Εκκαθάριση προεπιλεγμένων σε Ρυθμίσεις αρχικής σελίδας &gt; Εφαρμογές &gt; Διαχείριση εφαρμογών."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Επιλέξτε μια ενέργεια"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Δεν υπάρχουν εφαρμογές, οι οποίες μπορούν να εκτελέσουν αυτήν την ενέργεια."</string>
     <string name="aerr_title" msgid="653922989522758100">"Λυπούμαστε!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Υπήρξε μη αναμενόμενη διακοπή της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> (διαδικασία <xliff:g id="PROCESS">%2$s</xliff:g>). Προσπαθήστε ξανά."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 0a511eb..b8f624e 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Allows the application to control the vibrator."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"control flashlight"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Allows the application to control the flashlight."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"access USB devices"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Allows the application to access USB devices."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implement MTP protocol"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Allows access to the kernel MTP driver to implement the MTP USB protocol."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"test hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Erase the phone\'s data without warning by performing a factory data reset"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Set the device global proxy"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Set the device\'s global proxy to be used while policy is enabled. Only the first device admin sets the effective global proxy."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Set lock-screen password expiry"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Control how frequently the lock-screen password must be changed"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Set password expiry"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Control how long before lock-screen password needs to be changed"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Set storage encryption"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Require that stored application data be encrypted"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Use by default for this action."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Clear default in Home Settings &gt; Applications &gt; Manage applications."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Select an action"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"No applications can perform this action."</string>
     <string name="aerr_title" msgid="653922989522758100">"Sorry!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"The application <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has stopped unexpectedly. Please try again."</string>
@@ -883,7 +879,7 @@
     <string name="usb_storage_title" msgid="5901459041398751495">"USB connected"</string>
     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"You have connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android‘s USB storage."</string>
     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"You have connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android‘s SD card."</string>
-    <string name="usb_storage_button_mount" msgid="1052259930369508235">"Turn on USB storage"</string>
+    <string name="usb_storage_button_mount" msgid="1052259930369508235">"Turn off USB storage"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"There is a problem with using your USB storage for USB mass storage."</string>
     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"There is a problem with using your SD card for USB mass storage."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB connected"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 688565b..35d425b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -211,7 +211,7 @@
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"habilitar el modo de auto"</string>
     <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Permite que una aplicación habilite el modo auto."</string>
     <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"eliminar los procesos de fondo"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Permite que una aplicación elimine los procesos de fondo de otras aplicaciones, aun si la no queda poco espacio en la memoria."</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Permite que una aplicación elimine los procesos de fondo de otras aplicaciones, aun si la memoria no es baja."</string>
     <string name="permlab_forceStopPackages" msgid="1447830113260156236">"forzar la detención de otras aplicaciones"</string>
     <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Permite que una aplicación provoque la detención de otras aplicaciones."</string>
     <string name="permlab_forceBack" msgid="1804196839880393631">"provocar que la aplicación se acerque"</string>
@@ -257,7 +257,7 @@
     <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Se debe evitar utilizarlo en aplicaciones normales."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de widget. Se debe evitar utilizarlo en aplicaciones normales."</string>
-    <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivos"</string>
+    <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivo"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite que el propietario envíe sus intentos a un administrador de dispositivos. No se necesita para las aplicaciones normales."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar la orientación de la pantalla"</string>
     <string name="permdesc_setOrientation" msgid="6335814461615851863">"Admite una aplicación que cambia la rotación de la pantalla en cualquier momento. Se debe evitar utilizarlo en aplicaciones normales."</string>
@@ -277,12 +277,12 @@
     <string name="permdesc_installPackages" msgid="526669220850066132">"Admite una aplicación que instala paquetes de Android nuevos o actualizados. Las aplicaciones maliciosas pueden utilizarlo para agregar aplicaciones nuevas con permisos arbitrariamente potentes."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"eliminar todos los datos de memoria caché de la aplicación"</string>
     <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite que una aplicación libere espacio de almacenamiento en el tablet eliminando archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Permite que una aplicación libere espacio de almacenamiento en el teléfono borrando archivos del directorio de memoria caché de la aplicación. En general el acceso está muy restringido al proceso del sistema."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Admite una aplicación que libera espacio de almacenamiento en el teléfono al eliminar archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos de la aplicación"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite a una aplicación mover recursos de aplicación de medios internos a externos y viceversa."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"lee los datos confidenciales del registro"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permite que una aplicación lea diversos archivos de registro del sistema. Esto le permite descubrir información general acerca de lo que haces con el tablet, y puede potencialmente incluir información personal o privada."</string>
-    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permite que una aplicación lea los diversos archivos de registro del sistema. Esto le permite descubrir información general acerca de lo que haces con el teléfono, y puede potencialmente incluir información personal o privada."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Admite una aplicación que lee diversos archivos de registro del sistema. Esto te permite descubrir información general acerca de lo que haces con el teléfono, y puede potencialmente incluir información personal o privada."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"leer y escribir a recursos dentro del grupo de diagnóstico"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Admite una aplicación que lee y escribe a cualquier recurso dentro del grupo de diagnóstico; por ejemplo, archivos con /dev. Esto puede afectar potencialmente la estabilidad y la seguridad del sistema. Debe utilizarlo SÓLO el fabricante o el operador en los diagnósticos específicos del hardware."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"activar o desactivar componentes de la aplicación"</string>
@@ -296,15 +296,15 @@
     <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Permite a una aplicación modificar los datos de la configuración segura de los sistemas. Las aplicaciones normales no deben utilizarlo."</string>
     <string name="permlab_writeGservices" msgid="2149426664226152185">"modificar el mapa de servicios de Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Admite una aplicación que modifica el mapa de servicios de Google. Las aplicaciones normales no deben utilizarlo."</string>
-    <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"ejecutar automáticamente al iniciar"</string>
+    <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"iniciar automáticamente durante la inicialización"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permite que una aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que el tablet demore más en inicializar y que la aplicación retarde el funcionamiento total del tablet al estar en ejecución constante."</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Permite que una aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que el teléfono tarde más en inicializarse y que la aplicación demore el funcionamiento total del teléfono al estar en ejecución constante."</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Admite una aplicación que se inicia cuando el sistema haya finalizado la inicialización. Esto puede ocasionar que se demore más tiempo en inicializar el teléfono y que la aplicación retarde el funcionamiento total del teléfono al estar en ejecución constante."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"enviar emisiones pegajosas"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permite que una aplicación envíe emisiones adhesivas, que permanecen luego de que finaliza la emisión. Las aplicaciones maliciosas pueden hacer que la tableta funcione más lento y esté inestable haciendo que utilicen demasiada memoria."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Admite una aplicación que envía emisiones pegajosas, las cuales permanecen luego de que finaliza la emisión. Las aplicaciones maliciosas pueden hacer lento e inestable al teléfono, ya que ocasiona que utilice demasiada memoria."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"leer datos de contacto"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permite que una aplicación lea todos los datos de de contacto (direcciones) almacenados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para enviar tus datos a otras personas."</string>
-    <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Permite que una aplicación lea todos los datos (direcciones) de contactos almacenados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para enviar tus datos a otras personas."</string>
+    <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Admite una aplicación que lee todos los datos de (direcciones) de contactos almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de (dirección) guardados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Admite una aplicación que modifica los datos de (dirección de) contacto guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
@@ -340,9 +340,9 @@
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permite que la aplicación desactive todo el tablet de manera permanente. Esto es muy peligroso."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Admite que la aplicación desactive todo el teléfono de manera permanente. Esto es muy peligroso."</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forzar reinicio del tablet"</string>
-    <string name="permlab_reboot" product="default" msgid="2898560872462638242">"forzar reinicio del teléfono"</string>
+    <string name="permlab_reboot" product="default" msgid="2898560872462638242">"provocar el reinicio del teléfono"</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permite que la aplicación provoque el reinicio del tablet."</string>
-    <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Permite que la aplicación fuerce el reinicio del tablet."</string>
+    <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Admite que la aplicación provoque que el teléfono se reinicie."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"montar y desmontar filesystems"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Admite que la aplicación monte y desmonte filesystems para obtener almacenamiento extraíble."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"espacio de almacenamiento externo del formato"</string>
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Admite que la aplicación controle el vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar linterna"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Admite que la aplicación controle la linterna."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"acceder a dispositivos USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permite que la aplicación acceda a dispositivos USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementar protocolo MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite acceso al driver kernel MTP para implementar el protocolo MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"probar el hardware"</string>
@@ -374,7 +372,7 @@
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"llamar directamente a cualquier número de teléfono"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Admite que la aplicación llame a cualquier número de teléfono, incluidos los números de emergencia, sin tu intervención. Las aplicaciones maliciosas pueden realizar llamadas innecesarias e ilegales a los servicios de emergencia."</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directamente la configuración CDMA del tablet"</string>
-    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente la configuración CDMA del teléfono"</string>
+    <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"comienza directamente la configuración CDMA del teléfono"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Admite la aplicación para comenzar con el aprovisionamiento CDMA. Las aplicaciones maliciosas pueden comenzar con el aprovisionamiento CDMA sin necesidad."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar las notificaciones de actualización de ubicación"</string>
     <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Permite activar y desactivar las notificaciones de actualización de ubicación de la radio. Las aplicaciones normales no deben utilizarlo."</string>
@@ -429,7 +427,7 @@
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"cambiar la conectividad de la red"</string>
     <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Permite que una aplicación cambie el estado de la conectividad de red."</string>
     <string name="permlab_changeTetherState" msgid="2702121155761140799">"Cambiar la conectividad de anclaje a red"</string>
-    <string name="permdesc_changeTetherState" msgid="8905815579146349568">"ermite que una aplicación cambie el estado de la conectividad de anclaje a red."</string>
+    <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Permite que una aplicación cambie el estado de la conectividad de red del anclaje."</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"cambiar la configuración del uso de datos del fondo"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Admite una aplicación que cambia la configuración del uso de datos del fondo."</string>
     <string name="permlab_accessWifiState" msgid="8100926650211034400">"ver el estado de Wi-Fi"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Borrar los datos del teléfono sin advertencias al restablecer la configuración original"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Configura el proxy global de dispositivo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Configuración del proxy global de dispositivo que se utilizará mientras se habilita la política. Sólo la primera administración de dispositivo configura el proxy global efectivo."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Establecer la caducidad del bloqueo de pantalla"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar cuán a menudo se debe cambiar la contraseña de bloqueo de pantalla"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Establecer la caducidad de la contraseña"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Verifica cuánto tiempo antes debes cambiar la contraseña de la pantalla de bloqueo"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Establecer la encriptación del almacenamiento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requiere que los datos almacenados de la aplicación estén encriptados"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utilizar de manera predeterminada en esta acción."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Borrar la predeterminación en Configuración de la página principal &gt; Aplicaciones &gt; Administrar aplicaciones."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Seleccionar una acción"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Ninguna aplicación puede realizar esta acción."</string>
     <string name="aerr_title" msgid="653922989522758100">"¡Lo sentimos!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) se ha detenido de forma imprevista. Vuelve a intentarlo."</string>
@@ -835,7 +831,7 @@
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> se inició originalmente."</string>
     <string name="smv_application" msgid="295583804361236288">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha violado su política StrictMode autoimpuesta."</string>
     <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha violado su política StrictMode autoimpuesta."</string>
-    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> Correr"</string>
     <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Selecciona cambiar la aplicación"</string>
     <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"¿Deseas cambiar aplicaciones?"</string>
     <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Ya se está ejecutando una aplicación que debe detenerse antes de iniciar una nueva."</string>
@@ -923,17 +919,17 @@
     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Almacenamiento USB dañado. Es posible que debas reformatearlo."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string>
     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Almacenamiento USB extraído inesperadamente"</string>
-    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Almacenamiento USB extraído de forma imprevista"</string>
+    <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Tarjeta SD extraída de forma imprevista"</string>
     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desmontar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Es seguro extraer el almacenamiento USB"</string>
-    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Tarjeta SD fácil de extraer"</string>
     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puedes extraer de forma segura el almacenamiento USB."</string>
-    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes extraer de forma segura la tarjeta SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puedes eliminar la tarjeta SD sin riesgos."</string>
     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Almacenamiento USB extraído"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Tarjeta SD extraída"</string>
     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Almacenamiento USB eliminado. Insertar nuevos medios."</string>
-    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Tarjeta SD extraída. Insertar una nueva."</string>
+    <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Tarjeta SD eliminada. Inserta una nueva."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No se encontraron actividades coincidentes"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizar la estadística de uso de los componentes"</string>
     <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Permite la modificación de estadísticas recopiladas sobre el uso de componentes. Las aplicaciones normales no deben utilizarlo."</string>
@@ -966,8 +962,8 @@
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de túnel punto a punto"</string>
     <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clave compartida previamente"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificado"</string>
+    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Clave previamente compartida según L2TP/IPSec VPN"</string>
+    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificado según L2TP/IPSec VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -995,7 +991,7 @@
     <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Borrando almacenamiento USB..."</string>
     <string name="progress_erasing" product="default" msgid="2115214724367534095">"Borrando tarjeta SD..."</string>
     <string name="format_error" product="nosdcard" msgid="4320339096529911637">"No pudo borrar el almacenamiento USB."</string>
-    <string name="format_error" product="default" msgid="1343380371925238343">"No se pudo borrar la tarjeta SD."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"No pudo borrar la tarjeta SD."</string>
     <string name="media_bad_removal" msgid="7960864061016603281">"Se ha extraído la tarjeta SD antes de ser desmontada."</string>
     <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Se está verificando el almacenamiento USB en este momento."</string>
     <string name="media_checking" product="default" msgid="7334762503904827481">"Se está verificando la tarjeta SD en este momento."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 9ab0169..41fa758 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite que la aplicación controle la función de vibración."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar linterna"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite que la aplicación controle la función de linterna."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"acceso a dispositivos USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"La aplicación puede acceder a dispositivos USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementar protocolo MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite el acceso al controlador MTP del kernel para implementar el protocolo USB MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"probar hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Borrado de los datos del teléfono sin avisar restableciendo datos de fábrica"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir el servidor proxy global"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Define el servidor proxy global que se debe utilizar mientras la política esté habilitada. Solo el primer administrador de dispositivos define el servidor proxy global efectivo."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Definir caducidad bloqueo pantalla"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar la frecuencia con la que se debe cambiar el bloqueo de pantalla"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Definir caducidad de contraseña"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Permite controlar cuándo se debe cambiar la contraseña de bloqueo de la pantalla."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptación de almacenamiento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exige que se encripten los datos de la aplicación almacenados."</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utilizar de forma predeterminada para esta acción"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Borrar valores predeterminados en la página de configuración de la pantalla de inicio del teléfono &gt; Aplicaciones &gt; Administrar aplicaciones\"."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Seleccionar una acción"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Ninguna aplicación puede realizar esta acción."</string>
     <string name="aerr_title" msgid="653922989522758100">"Lo sentimos."</string>
     <string name="aerr_application" msgid="4683614104336409186">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) se ha interrumpido inesperadamente. Inténtalo de nuevo."</string>
@@ -978,7 +974,7 @@
     <string name="tethered_notification_message" msgid="3067108323903048927">"Toca para iniciar la configuración."</string>
     <string name="back_button_label" msgid="2300470004503343439">"Atrás"</string>
     <string name="next_button_label" msgid="1080555104677992408">"Siguiente"</string>
-    <string name="skip_button_label" msgid="1275362299471631819">"Saltar"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Omitir"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Uso elevado datos móviles"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Más información sobre uso de datos"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Límite datos superado"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 655f250..fa74391 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"به برنامه کاربردی اجازه می دهد لرزاننده را کنترل کند."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"کنترل چراغ قوه"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"به برنامه کاربردی اجازه می دهد چراغ قوه را کنترل کند."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"دسترسی به دستگاه های USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"به برنامه کاربردی اجازه می دهد به دستگاه های USB دسترسی پیدا کند."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"اعمال پروتکل MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"دسترسی به درایور کرنل MTP جهت اعمال پروتکل MTP USB را اجازه می دهد."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"تست سخت افزار"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"پاک کردن داده های گوشی بدون هشدار با انجام یک عملکرد بازنشانی داده های کارخانه"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تنظیم پروکسی جهانی دستگاه"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"پروکسی جهانی دستگاه مورد نظر را جهت استفاده هنگام فعال بودن خط مشی تنظیم کنید. فقط اولین سرپرست دستگاه پروکسی جهانی مفید را تنظیم می کند."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود قفل صفحه"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"کنترل تعداد دفعات تغییر رمز ورود قفل صفحه"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"تنظیم زمان انقضای رمز ورود"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"کنترل مدت زمانی که رمز ورود صفحه قفل قبل از تغییر یافتن لازم دارد"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"نیاز به رمزگذاری داده های برنامه کاربردی ذخیره شده دارد"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"استفاده به صورت پیش فرض برای این عملکرد."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"پاک کردن موارد پیش فرض در تنظیمات صفحه اصلی &gt; برنامه های کاربردی &gt; مدیریت برنامه ها."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"انتخاب یک عملکرد"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"هیچ برنامه ای نمی تواند این عملکرد را اجرا کند."</string>
     <string name="aerr_title" msgid="653922989522758100">"متأسفیم!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"برنامه کاربردی <xliff:g id="APPLICATION">%1$s</xliff:g> ( فرآیند <xliff:g id="PROCESS">%2$s</xliff:g>) به طور غیر منتظره ای متوقف شد. لطفاً دوباره امتحان کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 28312a1..9c525cf 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Antaa sovelluksen hallita värinää."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"hallitse taskulamppua"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Antaa sovelluksen hallita lamppua."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"käytä USB-tiloja"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Antaa sovelluksen käyttää USB-tiloja."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"ota käyttöön MTP-protokolla"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Antaa sovelluksen käyttää kernel-MTP-ajuria ja ottaa käyttöön MTP USB-protokollan."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testaa laitteistoa"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Tyhjennä puhelimen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Aseta laitteen yleinen välityspalvelin"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Aseta laitteen yleinen välityspalvelin käyttöön, kun käytäntö on käytössä. Vain ensimmäinen laitteen järjestelmänhallitsija voi asettaa käytettävän yleisen välityspalvelimen."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Aseta ruudunlukituksen salasanan voimassaoloaika"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Määritä, miten usein ruudunlukituksen salasana tulee vaihtaa"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Aseta salasanan voimassaoloaika"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valitse, kuinka pian ruudunlukituksen poiston salasana tulee vaihtaa"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Aseta tallennustilan salaus"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pakota tallennettujen sovellustietojen salaus"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Käytä oletuksena tälle toiminnolle."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Tyhjennä oletusasetus kohdassa Etusivun asetukset &gt; Sovellukset &gt; Hallinnoi sovelluksia."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Valitse toiminto"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Yksikään sovellus ei voi suorittaa tätä toimintoa."</string>
     <string name="aerr_title" msgid="653922989522758100">"Pahoittelemme!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Sovellus <xliff:g id="APPLICATION">%1$s</xliff:g> (prosessi <xliff:g id="PROCESS">%2$s</xliff:g>) pysähtyi yllättäen. Yritä uudelleen."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7a6c43a..39276af 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -126,7 +126,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisation"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
     <string name="low_memory" product="tablet" msgid="2292820184396262278">"La mémoire de la tablette est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
-    <string name="low_memory" product="default" msgid="6632412458436461203">"La mémoire du téléphone est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
+    <string name="low_memory" product="default" msgid="6632412458436461203">"La mémoire du téléphone est pleine ! Supprimez des fichiers pour libérer de l\'espace."</string>
     <string name="me" msgid="6545696007631404292">"Moi"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Options de la tablette"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Options du téléphone"</string>
@@ -159,8 +159,8 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vos messages"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Permet de lire et rédiger vos SMS, e-mails et autres messages."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vos informations personnelles"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accéder directement aux contacts et à l\'agenda enregistrés sur la tablette"</string>
-    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accéder directement aux contacts et à l\'agenda enregistrés sur votre téléphone"</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accéder directement aux contacts et à l\'agenda stockés sur la tablette"</string>
+    <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accédez directement aux contacts et à l\'agenda enregistrés sur votre téléphone."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Votre position"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Suivre votre position géographique"</string>
     <string name="permgrouplab_network" msgid="5808983377727109831">"Communications réseau"</string>
@@ -177,7 +177,7 @@
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Ces fonctionnalités sont réservées aux développeurs d\'applications."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stockage"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accéder à la  mémoire de stockage USB"</string>
-    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accéder à la carte SD"</string>
+    <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accès à la carte SD"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Désactivation ou modification de la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permet à une application de désactiver la barre d\'état ou d\'ajouter/supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"barre d\'état"</string>
@@ -193,7 +193,7 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"Envoi de messages SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Permet aux applications d\'envoyer des messages SMS. Des applications malveillantes peuvent entraîner des frais en envoyant des messages sans vous en demander la confirmation."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"Lecture des SMS ou MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permet à l\'application de lire les SMS enregistrés dans la mémoire de votre tablette ou sur votre carte SIM. Des applications malveillantes peuvent lire vos messages confidentiels."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permet à l\'application de lire les SMS stockés dans la mémoire de votre tablette ou sur votre carte SIM. Des applications malveillantes peuvent lire vos messages confidentiels."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Permet à l\'application de lire les SMS enregistrés dans la mémoire de votre téléphone ou sur votre carte SIM. Des applications malveillantes peuvent lire vos messages confidentiels."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"Modification de SMS ou de MMS"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permet à une application de modifier des messages SMS stockés sur votre tablette ou sur votre carte SIM. Des applications malveillantes peuvent ainsi supprimer vos messages."</string>
@@ -258,7 +258,7 @@
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service widget. Les applications standard ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur du périphérique"</string>
-    <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permet à l\'application d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standard ne devraient jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permet à l\'application d\'envoyer des intentions à l\'administrateur du périphérique. Les applications standard ne devraient jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"Changement d\'orientation de l\'écran"</string>
     <string name="permdesc_setOrientation" msgid="6335814461615851863">"Permet à une application de modifier la rotation de l\'écran à tout moment. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Envoi de signaux Linux aux applications"</string>
@@ -309,10 +309,10 @@
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet à une application de modifier les données (adresses) associées à vos contacts et stockées sur votre tablette. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de vos contacts."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permet à une application de modifier toutes les données de contact (adresses) enregistrées sur le téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier vos données de contact."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"lire des événements de l\'agenda"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre tablette. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet à une application de lire tous les événements d\'agenda stockés sur votre tablette. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"ajouter ou modifier des événements d\'agenda et envoyer des e-mails aux invités"</string>
-    <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Permet aux applications d\'ajouter ou de modifier des événements dans votre agenda, qui est susceptible d\'envoyer des e-mails aux invités. Des applications malveillantes peuvent exploiter cette fonctionnalité pour supprimer ou modifier des événements de l\'agenda ou envoyer des e-mails aux invités."</string>
+    <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Autorise les applications à ajouter ou à modifier des événements dans votre agenda, qui pourra envoyer des e-mails aux invités. Des logiciels malveillants peuvent utiliser cette fonctionnalité pour supprimer ou modifier des événements de l\'agenda ou envoyer des e-mails aux invités."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"Création de sources de localisation fictives à des fins de test"</string>
     <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Permet de créer des sources de localisation fictives à des fins de test. Des applications malveillantes peuvent utiliser cette fonctionnalité pour remplacer la position géographique et/ou l\'état fournis par des sources réelles comme le GPS ou les fournisseurs d\'accès."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Accès aux commandes de fournisseur de position géographique supplémentaires"</string>
@@ -321,10 +321,10 @@
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Créer des sources de données de localisation factices à des fins de test. Les applications malveillantes peuvent exploiter cette fonction pour remplacer la position géographique et/ou l\'état renvoyé par les sources de données de localisation réelles, telles que le GPS ou les fournisseurs réseau, ou pour surveiller et transmettre votre position géographique à une source externe."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"Localisation OK (GPS)"</string>
     <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Permet d\'accéder à des sources de localisation précises telles que le système GPS de la tablette, lorsque ces services sont disponibles. Des applications malveillantes peuvent exploiter cette fonctionnalité pour déterminer votre position, ce qui peut entraîner une utilisation accrue de la batterie."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Permet d\'accéder à des sources de localisation précises telles que le système GPS du téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent exploiter cette fonctionnalité pour déterminer votre position, ce qui peut entraîner une utilisation accrue de la batterie."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Permet d\'accéder à des sources de localisation précises comme le Global Positioning System (GPS) sur le téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer l\'endroit où vous vous trouvez et augmenter la consommation de la batterie de votre téléphone."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"Position géo. approximative (selon le réseau)"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Permet d\'accéder à des sources de localisation approximatives telles que des bases de données de réseaux mobiles pour déterminer la position géographique de la tablette lorsque celle-ci est disponible. Des applications malveillantes peuvent exploiter cette fonctionnalité pour déterminer votre position approximative."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Permet d\'accéder à des sources de localisation approximatives telles que des bases de données de réseaux mobiles pour déterminer la position géographique du téléphone, lorsque cette option est disponible. Des applications malveillantes peuvent exploiter cette fonctionnalité pour déterminer votre position approximative."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Accès à des sources de localisation approximative (par ex. des bases de données de réseaux mobiles) pour déterminer la position géographique du téléphone, lorsque cette option est disponible. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer approximativement l\'endroit où vous vous trouvez."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"Accès à SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Permet à certaines applications d\'utiliser les fonctionnalités SurfaceFlinger de bas niveau."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"Lecture de la mémoire tampon graphique"</string>
@@ -336,35 +336,33 @@
     <string name="permlab_camera" msgid="3616391919559751192">"prendre des photos et enregistrer des vidéos"</string>
     <string name="permdesc_camera" msgid="6004878235852154239">"Permet de prendre des photos et d\'enregistrer des vidéos avec l\'appareil photo. Cette fonctionnalité permet à l\'application de récupérer à tout moment les images perçues par l\'appareil."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"désactiver définitivement la tablette"</string>
-    <string name="permlab_brick" product="default" msgid="8337817093326370537">"désactiver définitivement le téléphone"</string>
+    <string name="permlab_brick" product="default" msgid="8337817093326370537">"Désactivation définitive du téléphone"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permet à l\'application de désactiver définitivement la tablette. Cette fonctionnalité est très dangereuse."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Permet à l\'application de désactiver définitivement le téléphone. Cette fonctionnalité est très dangereuse."</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forcer le redémarrage de la tablette"</string>
-    <string name="permlab_reboot" product="default" msgid="2898560872462638242">"forcer le redémarrage du téléphone"</string>
+    <string name="permlab_reboot" product="default" msgid="2898560872462638242">"Redémarrage forcé du téléphone"</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permet à l\'application de forcer le redémarrage de la tablette."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Permet à l\'application de forcer le redémarrage du téléphone."</string>
-    <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"Installer et désinstaller des systèmes de fichiers"</string>
-    <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permet à l\'application d\'installer et de désinstaller des systèmes de fichiers pour des périphériques de stockage amovibles."</string>
+    <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"Monter et démonter des systèmes de fichiers"</string>
+    <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permet à l\'application de monter et démonter des systèmes de fichiers pour des périphériques de stockage amovibles."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"Formatage du périphérique de stockage externe"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permet à l\'application de formater le périphérique de stockage amovible."</string>
     <string name="permlab_asec_access" msgid="3411338632002193846">"obtenir des informations sur la mémoire de stockage interne"</string>
-    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permet à l\'application d\'obtenir des informations sur la mémoire de stockage interne."</string>
-    <string name="permlab_asec_create" msgid="6414757234789336327">"créer une mémoire de stockage interne"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permet à l\'application d\'obtenir des informations sur le stockage interne."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"créer un stockage interne"</string>
     <string name="permdesc_asec_create" msgid="2621346764995731250">"Permet à l\'application de créer une mémoire de stockage interne."</string>
     <string name="permlab_asec_destroy" msgid="526928328301618022">"détruire la mémoire de stockage interne"</string>
-    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permet à l\'application de détruire la mémoire de stockage interne."</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permet à l\'application de détruire le stockage interne."</string>
     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"installer/désinstaller la mémoire de stockage interne"</string>
     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permet l\'installation ou la désinstallation de la mémoire de stockage interne par l\'application."</string>
     <string name="permlab_asec_rename" msgid="7496633954080472417">"renommer la mémoire de stockage interne"</string>
-    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permet à l\'application de renommer la mémoire de stockage interne."</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permet à l\'application de renommer le stockage interne."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"Contrôle du vibreur"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permet à l\'application de contrôler le vibreur."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"Contrôle de la lampe de poche"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permet à l\'application de contrôler la lampe de poche."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"accéder aux périphériques USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Autorise l\'application à accéder aux périphériques USB"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"mettre en œuvre le protocole MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permet l\'accès au pilote MTP du noyau à des fins de mise en œuvre du protocole USB MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"Tests du matériel"</string>
@@ -387,16 +385,16 @@
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"Lire l\'état et l\'identité du téléphone"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Permet à l\'application d\'accéder aux fonctionnalités d\'appel du téléphone. L\'application peut alors déterminer le numéro de téléphone et le numéro de série de l\'appareil, savoir si un appel est en cours, identifier le numéro appelé, etc."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"empêcher la tablette de passer en mode veille"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"empêcher le téléphone de passer en mode veille"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permet à une application d\'empêcher la tablette de passer en mode veille."</string>
-    <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Permet à une application d\'empêcher le téléphone de passer en mode veille."</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Arrêt du mode veille sur le téléphone"</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permet à une application d\'empêcher votre tablette de passer en mode veille."</string>
+    <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Permet à une application d\'empêcher votre téléphone de passer en mode veille."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"éteindre ou allumer la tablette"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"Éteindre ou allumer le téléphone"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permet à l\'application d\'éteindre et d\'allumer la tablette."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Permet à l\'application d\'éteindre et d\'allumer le téléphone."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"Exécution en mode Test d\'usine"</string>
     <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Permet d\'exécuter une application en mode test fabricant de faible niveau, autorisant ainsi l\'accès complet à la tablette. Cette fonctionnalité est uniquement disponible lorsque la tablette est en mode test fabricant."</string>
-    <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Permet d\'exécuter une application en mode test fabricant de faible niveau en autorisant ainsi l\'accès au téléphone. Cette fonctionnalité est uniquement disponible lorsque le téléphone est en mode test fabricant."</string>
+    <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Permet d\'exécuter en tant que test fabricant de faible niveau en autorisant l\'accès au matériel du téléphone. Cette fonctionnalité est uniquement disponible lorsque le téléphone est en mode de test fabricant."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"Configuration du fond d\'écran"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Permet à une application de définir le fond d\'écran du système."</string>
     <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"Sélection de la la taille du fond d\'écran"</string>
@@ -439,13 +437,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"autoriser la réception de données en Wi-Fi multidiffusion"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Autorise une application à recevoir des paquets qui ne sont pas directement adressés à votre mobile. Cela peut être utile pour la recherche de services disponibles à proximité. Consomme plus que le mode non multidiffusion."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"Gestion Bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permet à une application de configurer la tablette Bluetooth locale, d\'identifier des appareils distants et de les associer à la tablette."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permet à une application de configurer la tablette Bluetooth locale, de trouver des périphériques distants et de les associer à la tablette."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Permet à une application de configurer le téléphone Bluetooth local, d\'identifier des périphériques distants et de les associer au téléphone."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Création de connexions Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permet à une application d\'obtenir la configuration de la tablette Bluetooth locale, de se connecter à des appareils associés et d\'accepter leur connexion."</string>
-    <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permet à une application d\'obtenir la configuration du téléphone Bluetooth local, de se connecter à des appareils associés et d\'accepter leur connexion."</string>
+    <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permet à une application d\'obtenir la configuration du téléphone Bluetooth local et de créer et accepter des connexions à des appareils associés."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"contrôler la communication en champ proche"</string>
-    <string name="permdesc_nfc" msgid="9171401851954407226">"Permet à une application de communiquer avec des tags, cartes et lecteurs prenant en charge la communication en champ proche (NFC)."</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Autorise une application à communiquer avec des tags, cartes et lecteurs prenant en charge la communication en champ proche (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Désactivation du verrouillage des touches"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet à une application de désactiver le verrouillage des touches et toute sécurité par mot de passe. Exemple : Votre téléphone désactive le verrouillage du clavier lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Lecture des paramètres de synchronisation"</string>
@@ -463,7 +461,7 @@
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"Enregistrement dans le dictionnaire défini par l\'utilisateur"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permet à une application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur."</string>
     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modifier/supprimer le contenu de la mémoire de stockage USB"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modifier/supprimer le contenu de la carte SD"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"Modifier/supprimer le contenu de la carte SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Autorise une application à écrire sur la mémoire USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Autorise une application à écrire sur la carte SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modif./suppr. contenu mémoire interne support"</string>
@@ -476,18 +474,18 @@
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Gérer le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Surveiller le nombre de mots de passe incorrects saisis lors du déverrouillage de l\'écran et verrouiller la tablette ou effacer toutes ses données après un certain nombre de tentatives."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Surveiller le nombre de mots de passe incorrects saisis lors du déverrouillage de l\'écran et verrouiller le téléphone ou effacer toutes ses données après un certain nombre de tentatives"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Gérer le nombre de mots de passe incorrects saisis lors du déverrouillage de l\'écran et verrouiller le téléphone ou effacer toutes ses données après un certain nombre de tentatives"</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Modifier le mot de passe de déverrouillage de l\'écran"</string>
     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Modifier le mot de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Verrouiller l\'écran"</string>
     <string name="policydesc_forceLock" msgid="5696964126226028442">"Gérer le mode et les conditions de verrouillage de l\'écran"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Effacer toutes les données"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Effacer les données de la tablette sans avertissement, en restaurant la configuration usine"</string>
-    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Effacer les données du téléphone sans avertissement, en restaurant la configuration usine"</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Effacer les données de la tablette sans avertissement, en réinitialisant la configuration usine"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Effacer les données du téléphone sans avertissement, en restaurant les valeurs d\'usine"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Définir le proxy global du mobile"</string>
-    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Indiquer le proxy global à utiliser pour ce mobile lorsque les règles sont activées. Seul l\'administrateur principal du mobile peut définir le proxy global utilisé."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Définir exp. mot passe verr."</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Contrôler la fréquence de modification du mot de passe de verrouillage de l\'écran"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Indiquez le proxy global à utiliser pour ce mobile lorsque les règles sont activées. Seul l\'administrateur principal du mobile peut définir le proxy global utilisé."</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Définir la date d\'expiration du mot de passe"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Définir la fréquence de changement du mot de passe de verrouillage d\'écran"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Définir cryptage du stockage"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exiger que les données d\'application stockées soient cryptées"</string>
   <string-array name="phoneTypes">
@@ -608,11 +606,11 @@
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Saisissez le mot de passe pour procéder au déverrouillage."</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Saisissez le code PIN pour procéder au déverrouillage."</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Le code PIN est incorrect !"</string>
-    <string name="keyguard_label_text" msgid="861796461028298424">"Pour déverrouiller le clavier, appuyez sur \"Menu\" puis sur 0."</string>
+    <string name="keyguard_label_text" msgid="861796461028298424">"Pour débloquer le clavier, appuyez sur \"Menu\" puis sur 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Numéro d\'urgence"</string>
     <string name="lockscreen_carrier_default" msgid="8812714795156374435">"(Aucun service)"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Écran verrouillé"</string>
-    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Appuyez sur \"Menu\" pour déverrouiller le téléphone ou appeler un numéro d\'urgence"</string>
+    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Appuyez sur \"Menu\" pour débloquer le téléphone ou appeler un numéro d\'urgence"</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Appuyez sur \"Menu\" pour déverrouiller le téléphone."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Dessinez un schéma pour déverrouiller le téléphone"</string>
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Appel d\'urgence"</string>
@@ -637,8 +635,8 @@
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Vous avez mal reproduit le schéma de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Vous avez saisi un mot de passe incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Vous avez saisi un code PIN incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Vous avez saisi un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide de votre identifiant Google."\n\n" Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Vous avez mal saisi le schéma de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez déverrouiller votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Vous avez saisi un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez débloquer votre tablette à l\'aide de votre identifiant Google."\n\n" Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Vous avez mal saisi le schéma de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Schéma oublié ?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Déverrouillage du compte"</string>
@@ -650,7 +648,7 @@
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Nom d\'utilisateur ou mot de passe incorrect."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="8253152905532900548">"Vous avez oublié votre nom d\'utilisateur ou votre mot de passe ?"\n"Accédez à la page "<b>"google.com/accounts/recovery"</b></string>
     <string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Vérification..."</string>
-    <string name="lockscreen_unlock_label" msgid="737440483220667054">"Déverrouiller"</string>
+    <string name="lockscreen_unlock_label" msgid="737440483220667054">"Débloquer"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Son activé"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Son désactivé"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
@@ -676,8 +674,8 @@
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lire l\'historique et les favoris du navigateur"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"écrire dans l\'historique et les favoris du navigateur"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permet à une application de modifier l\'historique du navigateur ou les favoris enregistrés sur votre tablette. Des applications malveillantes peuvent exploiter cette fonctionnalité pour effacer ou modifier les données de votre navigateur."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permet à une application de modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent exploiter cette fonction pour effacer ou modifier les données de votre navigateur."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permet à une application de modifier l\'historique du navigateur ou les favoris stockés sur votre tablette. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de votre navigateur."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Autorise une application à modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonction pour effacer ou modifier les données de votre navigateur."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"régler le réveil"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet à l\'application de définir une alarme dans un utilitaire faisant office de réveil. Certains réveils risquent ne pas prendre en charge cette fonctionnalité."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifier les autorisations de géolocalisation du navigateur"</string>
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utiliser cette application par défaut pour cette action"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Effacer les paramètres par défaut dans les Paramètres de page d\'accueil &gt; Applications &gt; Gérer les applications."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Sélectionner une action"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Aucune application ne peut effectuer cette action."</string>
     <string name="aerr_title" msgid="653922989522758100">"Désolé !"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Fermeture soudaine de l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> (du processus <xliff:g id="PROCESS">%2$s</xliff:g>). Merci de réessayer."</string>
@@ -916,22 +912,22 @@
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Recherche d\'erreurs"</string>
     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Mémoire de stockage USB vide"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Carte SD vide"</string>
-    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"La mémoire de stockage USB est vide ou son système de fichiers n\'est pas pris en charge."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Le stockage USB est vide ou son système de fichiers n\'est pas pris en charge."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"La carte SD est vide ou son système de fichiers n\'est pas pris en charge."</string>
-    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Mémoire de stockage USB endommagée"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Stockage USB endommagé"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Carte SD endommagée"</string>
     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"La mémoire de stockage USB est endommagée. Un reformatage est peut-être nécessaire."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"La carte SD est endommagée. Vous devrez peut-être la reformater."</string>
-    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Mémoire de stockage USB retirée inopinément"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Mémoire USB retirée inopinément"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Carte SD retirée inopinément"</string>
     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Désinstaller la mémoire de stockage USB avant de la retirer pour éviter toute perte de données."</string>
-    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Désinstaller la carte SD avant de la retirer pour éviter toute perte de données."</string>
-    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"La mémoire de stockage USB peut être retirée en toute sécurité."</string>
+    <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Désactiver la carte SD avant de la retirer pour éviter toute perte de données."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Retirez la mémoire USB en toute sécurité."</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"La carte SD peut être retirée en toute sécurité"</string>
-    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Vous pouvez retirer la mémoire de stockage USB en toute sécurité."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"La mémoire de stockage USB peut être retirée en toute sécurité."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Vous pouvez retirer la carte SD en toute sécurité."</string>
     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Mémoire de stockage USB retirée"</string>
-    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Carte SD retirée"</string>
+    <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Carte SD manquante"</string>
     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Mémoire de stockage USB retirée. Insérez un nouveau support."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"La carte SD a été retirée. Insérez-en une autre."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Aucune activité correspondante trouvée"</string>
@@ -992,7 +988,7 @@
     <string name="action_mode_done" msgid="7217581640461922289">"OK"</string>
     <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Désinstallation de la mémoire de stockage USB..."</string>
     <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Désinstallation de la carte SD..."</string>
-    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Effacement de la mémoire de stockage USB..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Effacement de la  mémoire de stockage USB..."</string>
     <string name="progress_erasing" product="default" msgid="2115214724367534095">"Effacement de la carte SD..."</string>
     <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Impossible d\'effacer la mémoire de stockage USB"</string>
     <string name="format_error" product="default" msgid="1343380371925238343">"Impossible d\'effacer la carte SD"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 860bec9..2fd6d19 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Aplikaciji omogućuje nadzor nad vibracijom."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"nadzor bljeskalice"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Aplikaciji omogućuje nadzor nad bljeskalicom."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"pristupi USB uređajima"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Omogućuje aplikaciji pristup USB uređajima."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"Primjena MTP protokola"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Omogućuje pristup upravljačkom programu jezgre MTP-a radi implementacije MTP USB protokola."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testiranje hardvera"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Izbriši podatke telefona bez upozorenja vraćanjem u tvorničko stanje"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"postavi globalni proxy uređaja"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Postavi globalni proxy uređaja za upotrebu dok su pravila omogućena. Samo prvi administrator uređaja postavlja djelotvoran globalni proxy."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Post. istek zap. zaklj. zasl."</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nadzirite koliko se često mora mijenjati zaporka za zaključavanje zaslona"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Postavi istek zaporke"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nadzirite za koliko vremena zaporka za zaključani zaslon treba biti promijenjena"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Postavi enkripciju za pohranu"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Zahtijevaj da pohranjeni podaci aplikacije budu kriptirani"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Koristi se kao zadana postavka za ovu lokaciju."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Izbrišite zadane postavke u izborniku Početne postavke &gt; Aplikacije &gt; Upravljanje aplikacijama."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Odaberite radnju"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Tu radnju ne može izvesti nijedna aplikacija."</string>
     <string name="aerr_title" msgid="653922989522758100">"Žao nam je."</string>
     <string name="aerr_application" msgid="4683614104336409186">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> (postupak <xliff:g id="PROCESS">%2$s</xliff:g>) neočekivano je zaustavljen. Pokušajte ponovo."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index f962f35..aa4af42 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Lehetővé teszi az alkalmazás számára a rezgés vezérlését."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"vaku vezérlése"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Lehetővé teszi az alkalmazás számára a vaku vezérlését."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"USB-eszközök elérése"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Lehetővé teszi az alkalmazások számára az USB-eszközök elérését."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"MTP-protokoll megvalósítása"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Hozzáférést biztosít a kernel MTP illesztőprogramjához az MTP USB-protokoll megvalósításának céljából."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"hardver tesztelése"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Figyelmeztetés nélkül törli a telefon összes adatát, visszaállítva a gyári adatokat"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Az eszköz globális proxyjának beállítása"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Az eszköz globális proxyja lesz használatban, amíg az irányelv engedélyezve van. Csak az eszköz első rendszergazdája állíthatja be a tényleges globális proxyt."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Képernyőjelszó érvényessége"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Adja meg, hogy milyen gyakran kell módosítani a képernyőzár jelszavát"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Jelszó lejáratának beállítása"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Azt vezérli, mennyi időnként kell módosítani a képernyőt zároló jelszót"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Tárhelytitkosítás beállítása"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Megköveteli a tárolt alkalmazásadatok titkosítását"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Ez legyen az alapértelmezett program ehhez a művelethez."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Az alapértelmezés törlése a Főoldal beállításai &gt; Alkalmazások &gt; Alkalmazások kezelése menüben lehetséges."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Válasszon műveletet"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Egyik alkalmazás sem tudja végrehajtani ezt a műveletet."</string>
     <string name="aerr_title" msgid="653922989522758100">"Sajnáljuk!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás <xliff:g id="PROCESS">%2$s</xliff:g> folyamata váratlanul leállt. Kérjük, próbálja újra."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7b10651..eb14169 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Mengizinkan aplikasi mengontrol penggetar."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"mengontrol lampu senter"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Mengizinkan aplikasi mengontrol lampu senter."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"akses perangkat USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Mengizinkan aplikasi untuk perangkat USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementasikan protokol MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Izinkan akses pada driver MTP kernel untuk mengimplementasikan protokol USB MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"uji perangkat keras"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Hapus data ponsel tanpa peringatan, dengan menyetel ulang data pabrik"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setel proxy global perangkat"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Setel proxy global perangkat yang akandigunakan ketika kebijakan diaktifkan. Hanya admin perangkat pertama yang menyetel procy global yang berlaku."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Setel kedaluwarsa sandi pengunci layar"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrol seberapa sering sandi pengunci layar harus diganti"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Setel waktu kedaluwarsa sandi"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrol berapa lama sebelum sandi penguncian layar perlu diubah"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setel enkripsi penyimpanan"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Mengharuskan data aplikasi yang disimpan untuk dienkripsi"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Gunakan secara bawaan untuk tindakan ini."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Bersihkan bawaan pada Setelan Beranda &gt; Aplikasi &gt; Kelola aplikasi."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Pilih tindakan"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Tidak ada aplikasi dapat melakukan tindakan ini."</string>
     <string name="aerr_title" msgid="653922989522758100">"Maaf!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikasi (<xliff:g id="PROCESS">%2$s</xliff:g> proses) berhenti tiba-tiba. Harap coba lagi."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 76b6d1d..1507467 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Consente all\'applicazione di controllare la vibrazione."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controllo flash"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Consente all\'applicazione di controllare il flash."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"accesso a dispositivi USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Consente all\'applicazione di accedere ai dispositivi USB"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementa protocollo MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Consente di accedere al driver MTP del kernel per implementare il protocollo USB MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"esecuzione test hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dati di fabbrica"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Imposta il proxy globale del dispositivo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Imposta il proxy globale del dispositivo in modo da utilizzarlo mentre la norma è attiva. Il proxy globale effettivo è impostabile solo dal primo amministratore del dispositivo."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Imposta scadenza password blocco schermo"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabilisci la frequenza di modifica della password di blocco dello schermo"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Imposta scadenza password"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabilisci la scadenza della password di blocco dello schermo"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Imposta crittografia archivio"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Richiede la crittografia dei dati applicazione memorizzati"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Usa come predefinita per questa azione."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Cancella predefinita in Home &gt; Impostazioni &gt; Applicazioni &gt; Gestisci applicazioni."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Seleziona un\'azione"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Nessuna applicazione è in grado di svolgere questa azione."</string>
     <string name="aerr_title" msgid="653922989522758100">"Spiacenti."</string>
     <string name="aerr_application" msgid="4683614104336409186">"Interruzione imprevista dell\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>). Riprova."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1b597c8..7aa7b30 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"מאפשר ליישום לשלוט ברטט."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"שליטה בפנס"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"מאפשר ליישום לשלוט בפנס."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"גישה להתקני USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"מאפשר ליישום גישה להתקני USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"יישם פרוטוקול MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"מאפשר גישה למנהל התקן MTP של הליבה כדי ליישם פרוטוקול USB של MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"בדוק חומרה"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"מחק את נתוני הטלפון ללא אזהרה, על ידי ביצוע איפוס נתוני יצרן"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"הגדר את שרת ה-proxy הגלובלי של ההתקן"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"הגדר את שרת proxy הגלובלי של ההתקן לשימוש כאשר המדיניות מופעלת. רק מנהל ההתקן הראשון מגדיר את שרת ה-proxy הגלובלי הפעיל."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"הגדר תאריך תפוגה לסיסמה של נעילת המסך"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"שלוט בתדירות שבה הסיסמה של נעילת המסך חייבת להשתנות"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"הגדר תפוגת תוקף של סיסמה"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"שלוט בפרק הזמן הדרוש לשינוי הסיסמה של נעילת המסך"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"הגדר הצפנת אחסון"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"דורש שנתוני היישום המאוחסנים יהיו מוצפנים"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"השתמש כברירת מחדל עבור פעולה זו."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"נקה את ברירת המחדל ב\'הגדרות דף הבית\' &gt; \'יישומים\' &gt; \'נהל יישומים\'."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"בחר פעולה"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"אין יישומים שיכולים לבצע פעולה זו."</string>
     <string name="aerr_title" msgid="653922989522758100">"מצטערים!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"היישום <xliff:g id="APPLICATION">%1$s</xliff:g> (תהליך <xliff:g id="PROCESS">%2$s</xliff:g>) הופסק באופן לא צפוי. נסה שוב."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7594744..af2e4d4 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"バイブレーションの制御をアプリケーションに許可します。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ライトのコントロール"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"ライトの制御をアプリケーションに許可します。"</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"USBデバイスへのアクセス"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"USBデバイスへのアクセスをアプリケーションに許可します。"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"MTPプロトコルの実装"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"カーネルMTPドライバにアクセスしてMTP USBプロトコルを実装することを許可します。"</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"ハードウェアのテスト"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"警告せずにデータの初期化を実行して端末内のデータを消去します。"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"端末のグローバルプロキシを設定"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ポリシーが有効になっている場合は端末のグローバルプロキシが使用されるように設定します。有効なグローバルプロキシを設定できるのは最初のデバイス管理者だけです。"</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"解除パスワードの有効期限の設定"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"ロック解除パスワードの変更が必要になる頻度を指定します"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"パスワードの有効期限の設定"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"画面ロックパスワードの変更が必要になるまでの期間を指定します"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ストレージ暗号化の設定"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"保存したアプリケーションデータが暗号化されるようにする"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"常にこの操作で使用する"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"ホームの[設定]&gt;[アプリケーション]&gt;[アプリケーションの管理]でデフォルト設定をクリアします。"</string>
     <string name="chooseActivity" msgid="1009246475582238425">"操作の選択"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"この操作を実行できるアプリケーションはありません。"</string>
     <string name="aerr_title" msgid="653922989522758100">"エラー"</string>
     <string name="aerr_application" msgid="4683614104336409186">"<xliff:g id="APPLICATION">%1$s</xliff:g>(<xliff:g id="PROCESS">%2$s</xliff:g>)が予期せず停止しました。やり直してください。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a718344..6d1423c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"애플리케이션이 진동을 제어할 수 있도록 합니다."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"카메라 플래시 제어"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"애플리케이션이 카메라 플래시를 제어할 수 있도록 합니다."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"USB 장치 액세스"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"애플리케이션이 USB 장치에 액세스하도록 허용합니다."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"MTP 프로토콜 구현"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"커널 MTP 드라이버에 액세스하여 MTP USB 프로토콜을 구현할 수 있도록 허용합니다."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"하드웨어 테스트"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"공장 초기화를 수행하여 경고 없이 휴대전화 데이터를 지웁니다."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"기기 전체 프록시 설정"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"정책이 사용 설정되어 있는 동안 사용될 기기 전체 프록시를 설정합니다. 첫 번째 기기 관리자가 설정한 전체 프록시만 유효합니다."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"화면 잠금 비밀번호 만료 설정"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"화면 잠금 비밀번호 변경 빈도 설정"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"비밀번호 만료 설정"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"화면 잠금 비밀번호를 변경해야 하는 기간 변경"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"저장소 암호화 설정"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"저장한 애플리케이션 데이터를 암호화해야 합니다."</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"이 작업에 대해 기본값으로 사용"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"홈 설정 &gt; 애플리케이션 &gt; 애플리케이션 관리에서 기본값을 지웁니다."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"작업 선택"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"작업을 수행할 수 있는 애플리케이션이 없습니다."</string>
     <string name="aerr_title" msgid="653922989522758100">"죄송합니다."</string>
     <string name="aerr_application" msgid="4683614104336409186">"<xliff:g id="APPLICATION">%1$s</xliff:g> 애플리케이션(<xliff:g id="PROCESS">%2$s</xliff:g> 프로세스)이 예상치 않게 중지되었습니다. 다시 시도해 주세요."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2580af9..b0148154 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Leidžia programai valdyti vibratorių."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"valdyti šviesos signalą"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Leidžia programai valdyti šviesos signalą."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"pasiekti USB įrenginius"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Leidžiama programai pasiekti USB įrenginius."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"taikyti MTP protokolą"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Leidžiama prieiga prie pagrindinės MTP tvarkyklės taikyti MTP USB protokolą."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"bandyti aparatinę įrangą"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Be įspėjimo ištrinti telefono duomenis iš naujo nustatant gamyklinius duomenis"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nustatyti įrenginio bendrąjį tarpinį serverį"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nustatyti įrenginio bendrąjį tarpinį serverį, kad būtų naudojamas, kol įgalinta politika. Tik pirmasis įrenginio administratorius nustato efektyvų bendrąjį tarpinį serverį."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Nust. ekr. užr. slapt. gal. pab."</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valdykite, kaip dažnai reikia keisti ekrano užrakto slaptažodį"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Nustatyti slaptažodžio galiojimo pabaigą"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valdyti, per kiek laiko iki ekrano užrakinimo turi būti pakeistas slaptažodis"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nustatyti atmintinės šifruotę"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Saugomos programos duomenys turi būti šifruoti"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Šiam veiksmui tai naudoti pagal numatytuosius nustatymus."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Išvalykite numatytuosius nustatymus apsilankę „Pagrindiniai nustatymai“ &gt; „Programos“ &gt; „Valdyti programas“."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"pasirinkti veiksmą"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Šio veiksmo negali atlikti jokios programos."</string>
     <string name="aerr_title" msgid="653922989522758100">"Apgailestaujame!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Programa <xliff:g id="APPLICATION">%1$s</xliff:g> (<xliff:g id="PROCESS">%2$s</xliff:g> procesas) netikėtai sustojo. Bandykite dar kartą."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b7adf2d..3f69434 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Ļauj lietojumprogrammai kontrolēt vibrozvanu."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrolēt uzliesmojumu"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Ļauj lietojumprogrammai kontrolēt uzliesmojumu."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"piekļuve USB ierīcēm"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Ļauj lietojumprogrammai piekļūt USB ierīcēm."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"Ieviests MTP protokols"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Ļauj piekļūt kodola MTP dzinim, lai ieviestu MTP USB protokolu."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"pārbaudīt aparatūru"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Dzēš tālruņa datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Iestatīt ierīces globālo starpniekserveri"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Iestatiet izmantojamo ierīces globālo starpniekserveri, kad ir iespējota politika. Spēkā esošo globālo starpniekserveri iestata tikai pirmās ierīces administrators."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Ekr. bloķ. paroles term. iest."</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolē, cik bieži ir jāmaina ekrāna bloķēšanas parole."</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Paroles beigu termiņa iestatīšana"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolē ekrāna bloķēšanas paroles maiņas intervālu"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Skatīt atmiņas šifrējumu"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pieprasīt, lai saglabātie lietojumprogrammas dati tiktu šifrēti"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Pēc noklusējuma izmantot šai darbībai."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Notīriet noklusējumu šeit: Sākuma iestatījumi &gt; Lietojumprogrammas &gt; Lietojumprogrammu pārvaldība."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Atlasiet darbību"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Šo darbību nevar veikt neviena lietojumprogramma."</string>
     <string name="aerr_title" msgid="653922989522758100">"Atvainojiet!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Lietojumprogrammas <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) darbība neparedzēti tika apturēta. Lūdzu, mēģiniet vēlreiz."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index d3463fd..09a2cd4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Lar applikasjonen kontrollere vibratoren."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrollere lommelykten"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Lar applikasjonen kontrollere lommelykten."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"tilgang til USB-enheter"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Tillater programmet å få tilgang til USB-enheter."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementer MTP-protokoll"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Tillater tilgang til kjerne-MTP-driver for implementering av MTP USB-protokollen."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"teste maskinvare"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Tilbakestill telefonens data uten advarsel ved å utføre tilbakestilling til fabrikkstandard"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angi enhetens globale mellomtjener"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Angir den globale mellomtjeneren på enheten som skal brukes når regelen er aktivert. Kun den opprinnelige administratoren av enheten kan angi den globale mellomtjeneren."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Angi utløpsdato for skjermlåspassordet"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Velg hvor lenge det skal gå før passordet til skjermlåsen må byttes"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Angi utløpsdato for passordet"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Velg hvor lenge det skal gå før passordet til låseskjermen må byttes"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angi lagringskryptering"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Krever at lagrede programdata krypteres"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Bruk som standardvalg."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Fjern standardvalg i Innstillinger &gt; Applikasjoner &gt; Installerte applikasjoner."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Velg en aktivitet"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Ingen applikasjoner kan gjøre dette."</string>
     <string name="aerr_title" msgid="653922989522758100">"Beklager!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Applikasjonen <xliff:g id="APPLICATION">%1$s</xliff:g> (prosess <xliff:g id="PROCESS">%2$s</xliff:g>) stoppet uventet. Prøv igjen."</string>
@@ -924,7 +920,7 @@
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Minnekortet er skadet. Du må kanskje formatere det."</string>
     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-lagring fjernet uventet"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Minnekortet ble tatt ut uventet"</string>
-    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Koble fra USB-enheten før du tar den ut for å unngå tap av data."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Koble fra USB-lagring før enheten tas ut av maskinen for å unngå tap av data."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string>
     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB-lagring kan trygt fjernes"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Trygt å ta ut minnekort"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 68ab40c..85a7a2d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Hiermee kan de app de trilstand beheren."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"zaklamp bedienen"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Hiermee kan de app de zaklamp bedienen."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"toegang krijgen tot USB-apparaten"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Hiermee kan de app toegang krijgen tot USB-apparaten."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"MTP-protocol implementeren"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Staat toegang tot de kernel van de MTP-driver toe voor het implementeren van het MTP-USB-protocol."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"hardware testen"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"De gegevens van de telefoon zonder waarschuwing wissen door de fabrieksinstellingen te herstellen"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Algemene proxy voor het apparaat instellen"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Stel de algemene proxy voor het apparaat in die moet worden gebruikt terwijl het beleid is geactiveerd. Alleen de eerste apparaatbeheerder stelt de algemene proxy in."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Verval wachtwoord instellen"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheren hoe vaak het wachtwoord voor schermvergrendeling moet worden gewijzigd"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Verval wachtwoord instellen"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheren hoe lang het duurt voordat het wachtwoord voor schermvergrendeling moet worden gewijzigd"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Codering voor opslag instellen"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vereisen dat opgeslagen toepassingsgegevens kunnen worden gecodeerd"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Standaard gebruiken voor deze actie."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Wis standaardinstelling via startscherm: \'Instellingen\' &gt; \'Toepassingen\' &gt; \'Toepassingen beheren\'."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Een actie selecteren"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Geen enkele app kan deze actie uitvoeren."</string>
     <string name="aerr_title" msgid="653922989522758100">"Helaas!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"De app <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) is onverwachts gestopt. Probeer het opnieuw."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4c5f062..99f723c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Pozwala aplikacjom na kontrolowanie wibracji."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrolowanie latarki"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Pozwala aplikacji kontrolować latarkę."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"dostęp do urządzeń USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Zezwala aplikacji na dostęp do urządzeń USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementowanie protokołu MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Zezwala na dostęp do sterownika MTP jądra w celu implementacji protokołu USB MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testowanie sprzętu"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Wymazywanie danych z telefonu bez ostrzeżenia, przez przywrócenie danych fabrycznych"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ustaw globalny serwer proxy urządzenia"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ustaw globalny serwer proxy urządzenia do wykorzystywania przy włączonych zasadach. Tylko pierwszy administrator urządzenia ustawia obowiązujący globalny serwer proxy."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Ustaw wygasanie hasła blokady"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrola częstości zmian hasła ekranu blokady"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Ustaw wygasanie hasła"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrola czasu, po którym należy zmienić hasło blokowania ekranu"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ustaw szyfrowanie pamięci"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Wymaga szyfrowania danych zapisanych aplikacji"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Używaj domyślnie dla tej czynności."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Wyczyść domyślne w: Ustawienia strony głównej &gt; Aplikacje &gt; Zarządzaj aplikacjami."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Wybierz czynność"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Żadna z aplikacji nie może wykonać tej czynności."</string>
     <string name="aerr_title" msgid="653922989522758100">"Przepraszamy!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) została niespodziewanie zatrzymana. Spróbuj ponownie."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 014bf88..9c069c4 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite à aplicação controlar o vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar lanterna"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite à aplicação controlar a lanterna."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"aceder a dispositivos USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permite à aplicação aceder a dispositivos USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementar protocolo MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite o acesso ao controlador MTP de kernel para implementar o protocolo MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testar hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Apagar os dados do telefone sem avisar, ao efectuar uma reposição de dados de fábrica"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do aparelho"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Definir o proxy global do aparelho a ser utilizado quando a política estiver activada. Só o primeiro administrador do aparelho define o proxy global efectivo."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Def. valid. palavra-passe bloq. ecrã"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a palavra-passe deve ser alterada"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Definir tempo de validade da palavra-passe"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controle com que antecedência é necessário alterar a palavra-passe de bloqueio do ecrã"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Def. encriptação armazenamento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requerer encriptação dos dados da aplicação armazenados"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utilizar por predefinição para esta acção."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Limpar predefinição em Definições iniciais &gt; Aplicações &gt; Gerir aplicações."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Seleccionar uma acção"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Nenhuma aplicação pode efectuar esta acção."</string>
     <string name="aerr_title" msgid="653922989522758100">"Lamentamos."</string>
     <string name="aerr_application" msgid="4683614104336409186">"A aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) parou de forma inesperada. Tente novamente."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 07907fb..e8b230f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite que o aplicativo controle o vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar lanterna"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite que o aplicativo controle a lanterna."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"acessar dispositivos USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permitir que o aplicativo acesse dispositivos USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementar protocolo MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite acesso ao driver MTP do núcleo para implementar o protocolo USB MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testar hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Apaga os dados do telefone sem aviso, executando uma redefinição da configuração original"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir o proxy global do dispositivo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Configura o proxy global do dispositivo para ser usado enquanto a política estiver ativada. Somente o primeiro administrador do dispositivo pode configurar um verdadeiro proxy global."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Definir val. da senha de bloqueio"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a senha da tela de bloqueio deve ser alterada"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Definir validade da senha"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controle quanto tempo uma senha de bloqueio de tela deve ficar ativa antes de ser alterada"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Definir criptografia de armazenamento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exigir que os dados do aplicativo armazenado sejam criptografados"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Usar como padrão para esta ação."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Limpar o padrão em Configurações da página inicial &gt; Aplicativos &gt; Gerenciar aplicativos."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Selecionar uma ação"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Nenhum aplicativo pode realizar esta ação."</string>
     <string name="aerr_title" msgid="653922989522758100">"Desculpe!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"O aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) parou inesperadamente. Tente novamente."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index bc1e133..f3073bd 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -367,10 +367,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permetta a l\'applicaziun da controllar la vibraziun."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controllar la glischina"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permetta a l\'applicaziun da controllar la glischina."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"acceder ad apparats USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permetta a l\'applicaziun dad acceder als apparats periferics USB."</string>
     <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
     <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
@@ -867,8 +865,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Utilisar questa applicaziun sco standard per questa acziun."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Stizzar ils parameters da standard en Parameters da la pagina da partenza &gt; Applicaziuns &gt; Administrar las applicaziuns."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Tscherner ina acziun"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Nagina applicaziun po exequir questa acziun."</string>
     <string name="aerr_title" msgid="653922989522758100">"Perstgisai!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"L\'applicaziun <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) è vegnida serrada nunspetgadamain. Empruvai anc ina giada."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 59fc5c9..217c965 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite aplicaţiei să controleze mecanismul de vibrare."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"control lanternă"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite aplicaţiei să controleze lanterna."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"accesare dispozitive USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permite aplicaţiei să acceseze dispozitive USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementare protocol MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Permite accesul la driverul MTP al nucleului pentru a implementa protocolul USB pentru MTP."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testare hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Ştergeţi datele din telefon fără avertisment, efectuând resetarea configurării din fabrică"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setaţi serverul proxy global pentru dispozitiv"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Setaţi serverul proxy global pentru dispozitiv care să fie utilizat cât timp politica este activă. Numai primul administrator al dispozitivului poate seta serverul proxy global activ."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Expirare parolă blocare ecran"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabiliţi frecvenţa de schimbare a parolei de blocare a ecranului"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Setaţi expirarea parolei"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlarea duratei până când parola de blocare a ecranului trebuie modificată"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setaţi criptarea stocării"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Necesită ca datele aplicaţiei stocate să fie criptate"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Se utilizează în mod prestabilit pentru această acţiune."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Ştergeţi setările prestabilite din Setări pagină de pornire &gt; Aplicaţii &gt; Gestionare aplicaţii."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Selectaţi o acţiune"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Această acţiune nu poate fi efectuată de nicio aplicaţie."</string>
     <string name="aerr_title" msgid="653922989522758100">"Ne pare rău!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Aplicaţia <xliff:g id="APPLICATION">%1$s</xliff:g> (procesul <xliff:g id="PROCESS">%2$s</xliff:g>) s-a oprit în mod neaşteptat. Încercaţi din nou."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c4e68a9..405fbc0 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Позволяет приложению управлять виброзвонком."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"управлять вспышкой"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Позволяет приложению управлять вспышкой."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"доступ к USB-устройствам"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Позволяет приложению получать доступ к USB-устройствам."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"Реализовать протокол MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Разрешает доступ к драйверу основного устройства MTP для реализации протокола MTP USB"</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"проверять аппаратное обеспечение"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Уничтожить все данные на телефоне без предупреждения путем сброса настроек"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Глобальный прокси-сервер"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Настройте глобальный прокси-сервер устройства, который будет использоваться при активной политике. Глобальный прокси-сервер должен настроить первый администратор устройства."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Задать срок действия пароля"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Укажите, как часто следует менять пароль блокировки экрана"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Задать время действия пароля"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Задать время действия пароля перед появлением экрана блокировки"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Настроить шифрование хранилища"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Требует шифровать данные приложений, находящиеся в хранилище."</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"По умолчанию для этого действия"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Удалить настройки по умолчанию: главный экран &gt; \"Настройки\" &gt; \"Приложения\" &gt; \"Управление приложениями\"."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Выберите действие"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Это действие не может выполнять ни одно приложение."</string>
     <string name="aerr_title" msgid="653922989522758100">"Ошибка приложения!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Произошла неожиданная остановка приложения <xliff:g id="APPLICATION">%1$s</xliff:g> (процесс <xliff:g id="PROCESS">%2$s</xliff:g>). Повторите попытку."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 5d10d27..9605af2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Umožňuje aplikácii ovládať vibrácie."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ovládanie kontrolky"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Umožňuje aplikácii ovládať kontrolku."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"prístup k zariadeniam USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Umožní aplikácii prístup k zariadeniam USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementovať protokol MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Povoľuje prístup k ovládaču kernel MTP na implementáciu protokolu MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testovanie hardvéru"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Bez predchádzajúceho upozornenia zmazať všetky údaje tým, že sa obnovia továrenské nastavenia telefónu"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastaviť globálny server proxy zariadenia"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globálny server proxy, ktorý sa bude používať po aktivácii pravidiel. Platný globálny server proxy nastavuje iba prvý správca zariadenia."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Nastav. koniec platnosti hesla"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nastavte, ako často sa musí zmeniť heslo na uzamknutie obrazovky"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Nastaviť dátum vypršania platnosti hesla"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ovládanie doby, po uplynutí ktorej treba zmeniť heslo na odomknutie obrazovky"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastaviť šifr. ukl. priestoru"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vyžaduje šifrovanie uložených údajov aplikácií"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Použiť ako predvolené nastavenie pre túto akciu."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Vymazanie predvolených hodnôt v časti Nastavenia plochy &gt; Aplikácie &gt; Správa aplikácií."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Vyberte akciu"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Túto akciu nemôžu vykonávať žiadne aplikácie."</string>
     <string name="aerr_title" msgid="653922989522758100">"Je nám ľúto!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) bola neočakávane zastavená. Skúste to znova."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3d003fb..a460627 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Programu dovoljuje nadzor vibriranja."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"nadzor svetilke"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Programu dovoljuje nadzor svetilke."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"dostop do naprav USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Programu omogoča dostop do naprav USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"uveljavitev protokola MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Omogoča dostop do gonilnika jedra MTP za uveljavitev protokola MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"preskušanje strojne opreme"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Brisanje (s tovarniško ponastavitvijo) vseh podatkov v telefonu brez opozorila"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastavitev globalnega strežnika proxy za napravo"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nastavite globalni strežnik proxy naprave, ki bo v uporabi, ko je pravilnik omogočen. Samo skrbnik prve naprave lahko nastavi veljaven globalni strežnik proxy."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavitev poteka gesla za zaklepanje zaslona"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Določite, kako pogosto je treba spremeniti geslo za zaklepanje zaslona"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Nastavitev poteka gesla"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nastavite, koliko časa prej je treba spremeniti geslo za odklepanje zaslona"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavitev šifriranja shrambe"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Shranjeni podatki programa morajo biti šifrirani"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Privzeta uporaba za to dejanje."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Počistite privzete nastavitve v razdelku Osnovne nastavitve &gt; Programi &gt; Upravljanje programov."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Izberite dejanje"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Tega dejanja ne more izvesti noben program."</string>
     <string name="aerr_title" msgid="653922989522758100">"Oprostite."</string>
     <string name="aerr_application" msgid="4683614104336409186">"Program <xliff:g id="APPLICATION">%1$s</xliff:g> (postopek <xliff:g id="PROCESS">%2$s</xliff:g>) se je nepričakovano ustavil. Poskusite znova."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a8d9e29..a6f1e5f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Омогућава да апликација контролише вибрације."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"контрола осветљења"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Омогућава да апликација контролише осветљење."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"приступ USB уређајима"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Омогућава апликацији приступ USB уређајима."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"примени MTP протокол"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Омогућава приступ основном MTP управљачком програму ради примене MTP USB протокола."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"тестирање хардвера"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Брисање података на телефону без упозорења враћањем фабричких података"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Подесите глобални прокси сервер уређаја"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Подесите глобални прокси сервер уређаја који ће се користити док су омогућене смернице. Само први администратор уређаја поставља ефективни глобални прокси сервер."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Подешавање истека лозинке екрана"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролишите колико често лозинка за закључавање екрана мора да се мења"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Подеси време истека лозинке"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролишите време када лозинка за закључавање екрана треба да се промени"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Подешавање шифровања складишта"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Захтева да сачувани подаци апликације буду шифровани"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Подразумевано користи за ову радњу."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Обришите подразумевана подешавања у оквиру ставки Подешавања почетне странице &gt; Апликације &gt; Управљање апликацијама."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Избор радње"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Ниједна апликација не може да изврши ову радњу."</string>
     <string name="aerr_title" msgid="653922989522758100">"Жао нам је!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Апликација <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) је неочекивано заустављена. Покушајте поново."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 9b93047..1c234c2 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Tillåter att programmet styr vibratorn."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"styra lampa"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Tillåter att programmet styr lampan."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"åtkomst till USB-enheter"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Tillåter att programmet använder USB-enheter."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"implementera MTP-protokoll"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Ger åtkomst till MTP-kerneldrivrutinen för att implementera MTP/USB-protokollet."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testa maskinvara"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Ta bort data från telefonen utan förvarning genom att återställa standardinställningarna"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ange global proxyserver"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Ange vilken global proxyserver som ska användas när policyn är aktiverad. Endast den första enhetsadministratören anger den faktiska globala proxyservern."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Ange lösenordets utgångsdatum"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Styr hur ofta lösenordet till skärmlåset måste ändras"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Ange lösenordets utgångsdatum"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Se hur långt det är kvar till du måste ändra lösenordet till låsningsskärmen"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ange krypterad lagring"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kräv att sparade applikationsdata krypteras."</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Använd som standard för denna åtgärd."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Rensa standardinställning i Startinställningar &gt; Appar &gt; Hantera appar."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Välj en åtgärd"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Inga appar kan utföra den här åtgärden."</string>
     <string name="aerr_title" msgid="653922989522758100">"Tyvärr!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Processen <xliff:g id="PROCESS">%2$s</xliff:g> för programmet <xliff:g id="APPLICATION">%1$s</xliff:g> stoppades oväntat. Försök igen."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 62dfc29..90747d7 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"อนุญาตให้แอปพลิเคชันควบคุมการสั่นเตือน"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ควบคุมไฟฉาย"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"อนุญาตให้แอปพลิเคชันควบคุมไฟฉาย"</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"เข้าถึงอุปกรณ์ USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"อนุญาตให้แอปพลิเคชันเข้าถึงอุปกรณ์ USB"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"ใช้โปรโตคอล MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"อนุญาตการเข้าถึงไดรเวอร์ Kernel MTP เพื่อใช้โปรโตคอล MTP USB"</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"ทดสอบฮาร์ดแวร์"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"ลบข้อมูลของโทรศัพท์โดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์ที่จะใช้ขณะเปิดการใช้งานนโยบาย เฉพาะผู้ดูแลอุปกรณ์คนแรกเท่านั้นที่ตั้งค่าพร็อกซีส่วนกลางที่มีผลบังคับ"</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"ตั้งค่าวันหมดอายุของรหัสผ่านล็อกหน้าจอ"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"ควบคุมความถี่ในการเปลี่ยนรหัสผ่านล็อกหน้าจอ"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"ตั้งค่าการหมดอายุของรหัสผ่าน"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"ควบคุมระยะเวลาก่อนที่จะต้องเปลี่ยนรหัสผ่านการล็อกหน้าจอ"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ตั้งค่าการเข้ารหัสที่เก็บข้อมูล"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"กำหนดว่าแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"ใช้ค่าเริ่มต้นสำหรับการทำงานนี้"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"ล้างข้อมูลค่าเริ่มต้นในการตั้งค่าหน้าแรก &gt; แอปพลิเคชัน &gt; จัดการแอปพลิเคชัน"</string>
     <string name="chooseActivity" msgid="1009246475582238425">"เลือกการทำงาน"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"ไม่มีแอปพลิเคชันใดทำงานนี้ได้"</string>
     <string name="aerr_title" msgid="653922989522758100">"ขออภัย!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"แอปพลิเคชัน <xliff:g id="APPLICATION">%1$s</xliff:g> (กระบวนการ <xliff:g id="PROCESS">%2$s</xliff:g> หยุดทำงานโดยไม่คาดหมาย โปรดลองอีกครั้ง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 08c3ff7..713fca9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Pinapayagan ang application na kontrolin ang vibrator."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrolin ang flashlight"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Pinapayagan ang application na kontrolin ang flashlight."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"i-access ang mga USB device"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Pinapayagan ang application na i-access ang mga USB device."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"ipatupad ang MTP protocol"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Pinapayagan ang access sa kernel MTP driver upang maipatupad ang MTP USB protocol."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"subukan ang hardware"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Burahin ang data ng telepono nang walang babala, sa pamamagitan ng pagsasagawa ng pag-reset sa data ng factory"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Itakda ang pandaigdigang proxy ng device"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Itakda ang pandaigdigang proxy ng device na gagamitin habang pinagana ang patakaran. Tanging ang unang admin ng device ang magtatakda sa may bisang pandaigdigang proxy."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Itakda expire password pag-lock scr"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolin kung gaano kadalas dapat na mapalitan ang password sa pag-lock ng screen"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Itakda pag-expire ng password"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolin kung gaano katagal bago kailangang palitan ang password sa pag-lock ng screen"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Itakda pag-encrypt ng imbakan"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Hinging naka-encrypt ang nakaimbak na data ng application"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Gamitin bilang default para sa pagkilos na ito."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"I-clear ang default sa Mga Setting ng Home &gt; Mga Application &gt; Pamahalaan ang mga application."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Pumili ng pagkilos"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Walang mga application ang makakapagsagawa ng pagkilos na ito."</string>
     <string name="aerr_title" msgid="653922989522758100">"Paumanhin!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Hindi inaasahang humito ang <xliff:g id="APPLICATION">%1$s</xliff:g> (proseso <xliff:g id="PROCESS">%2$s</xliff:g>) ng application. Pakisubukang muli."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 0b0ef01..d7a5008 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Uygulamanın titreşimi denetlemesine izin verir."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"flaşı denetle"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Uygulamaların flaş ışığını denetlemesine izin verir."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"USB cihazlarına erişme"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Uygulamaların USB cihazlarına erişimine izin verir"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"MTP protokolünü uygula"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"MTP USB protokolünü uygulamak için çekirdekteki MTP sürücüsüne erişim izni ver."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"donanımı test et"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek telefondaki verileri uyarıda bulunmadan silin"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Cihaz genelinde geçerli proxy\'i ayarla"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Politika etkin olduğunda kullanılacak cihaz genelinde geçerli proxy\'yi ayarlayın. Etkin genel proxy\'yi yalnızca ilk cihaz yöneticisi ayarlar."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Ekr kilt şifr süre sonu ayarla"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ekran kilitleme şifresinin hangi sıklıkla değiştirilmesi gerektiğini denetleyin"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Şifre süre sonu tarihi ayarla"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ekran kilitleme şifresinin ne kadar süre sonra değiştirilmesi gerekeceğini denetleyin."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Deplm şifrelemesini ayarla"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Depolanan uygulama verisinin şifrelenmiş olmasını gerektir"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Varsayılan olarak bu işlem için kullan."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Giriş Ayarları &gt; Uygulamalar &gt; Uygulamaları yönet\'te varsayılanı temizleyin."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"İşlem seç"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Hiçbir uygulama bu işlemi yapamaz."</string>
     <string name="aerr_title" msgid="653922989522758100">"Üzgünüz!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması (<xliff:g id="PROCESS">%2$s</xliff:g> işlemi) beklenmedik biçimde durdu. Lütfen yeniden deneyin."</string>
@@ -828,7 +824,7 @@
     <string name="anr_application_process" msgid="4185842666452210193">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması (<xliff:g id="PROCESS">%2$s</xliff:g> işleminde) yanıt vermiyor."</string>
     <string name="anr_process" msgid="1246866008169975783">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi yanıt vermiyor."</string>
     <string name="force_close" msgid="3653416315450806396">"Kapanmaya zorla"</string>
-    <string name="report" msgid="4060218260984795706">"Bildir"</string>
+    <string name="report" msgid="4060218260984795706">"Rapor"</string>
     <string name="wait" msgid="7147118217226317732">"Bekle"</string>
     <string name="launch_warning_title" msgid="8323761616052121936">"Uygulama yönlendirildi"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> şimdi çalışıyor."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index eabbea1..7c329c5 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Дозволяє програмі контролювати вібросигнал."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"контр. блим. світло"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Дозволяє програмі контролювати світловий сигнал."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"отр.дост.до прист.USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Дозволяє програмі отрим. доступ до пристр. USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"впроваджувати протокол MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Дозволяє доступ до драйвера ядра MTP для впровадження протоколу MTP (USB)."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"тест-ти обладн."</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Видаляє дані телефону без попередження, відновлюючи заводські налаштування"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Установ. глоб. проксі пристрою"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Устан. використ. глоб. проксі, коли ввімкнено політику. Лише адміністратор першого пристрою встановлює активний глоб. проксі."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Установити термін дії пароля блокування екрана"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролювати частоту зміни пароля блокування екрана"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Установити термін дії пароля"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Регулює, за скільки часу перед блокуванням екрана треба змінювати пароль"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Установити шифрування носія"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Потрібно, щоб дані збереженої програми були зашифровані"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Використ. за умовч. для цієї дії."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Очист. налашт. за умовч. у Дом. налашт. &gt; Програми &gt; Керув. програмами."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Виберіть дію"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Жодна програма не може виконати цю дію."</string>
     <string name="aerr_title" msgid="653922989522758100">"Помилка!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Програма <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) несподівано зупинилася. Спробуйте ще."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 812004b..49c9e44 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Cho phép ứng dụng kiểm soát bộ rung."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kiểm soát đèn nháy"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Cho phép ứng dụng kiểm soát đèn nháy."</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"truy cập bộ nhớ USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Cho phép ứng dụng truy cập thiết bị USB."</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"triển khai giao thức MTP"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Cho phép truy cập tới trình điều khiển MTP nhân hệ điều hành để triển khai giao thức MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"kiểm tra phần cứng"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Xóa dữ liệu trên điện thoại mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Đặt proxy chung của điện thoại"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Đặt proxy chung của điện thoại được sử dụng trong khi chính sách được bật. Chỉ quản trị viên đầu tiên của điện thoại mới có thể đặt proxy chung hiệu quả."</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"Đặt hết hạn mật khẩu khóa màn hình"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kiểm soát tần suất bắt buộc phải thay đổi mật khẩu khóa màn hình"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"Đặt hết hạn mật khẩu"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kiểm soát thời lượng trước khi mật khẩu khóa màn hình cần được thay đổi"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Đặt mã hóa dung lượng lưu trữ"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Yêu cầu dữ liệu ứng dụng được lưu trữ phải được mã hóa"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"Sử dụng theo mặc định đối với tác vụ này."</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Xoá mặc định trong Cài đặt Màn hình trang chủ &gt; Ứng dụng&gt; Quản lý ứng dụng."</string>
     <string name="chooseActivity" msgid="1009246475582238425">"Chọn tác vụ"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"Không ứng dụng nào có thể thực hiện tác vụ này."</string>
     <string name="aerr_title" msgid="653922989522758100">"Rất tiếc!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"Ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> (quá trình <xliff:g id="PROCESS">%2$s</xliff:g>) đã dừng đột ngột. Vui lòng thử lại."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 3b70dd7..640b9bc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"允许应用程序控制振动器。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"控制闪光灯"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"允许应用程序控制闪光灯。"</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"访问 USB 设备"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"允许应用程序访问 USB 设备。"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"应用 MTP 协议"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"允许访问内核 MTP 驱动程序,以便应用 MTP USB 协议。"</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"测试硬件"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"恢复出厂设置时,将擦除手机上的数据而不发送警告"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"设置设备全局代理"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"请设置在启用政策的情况下要使用的设备全局代理。只有第一设备管理员才可设置有效的全局代理。"</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"设置锁定屏幕密码的有效期"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制锁定屏幕密码的更改频率"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"设置密码有效期"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制屏幕锁定密码的使用期限"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"设置存储设备加密"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"需要对存储的应用程序数据进行加密"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"默认使用此方式发送。"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"通过主屏幕上的“设置”&gt;“应用程序”&gt;“管理应用程序”清除默认设置。"</string>
     <string name="chooseActivity" msgid="1009246475582238425">"选择一项操作"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"没有应用程序可执行此操作。"</string>
     <string name="aerr_title" msgid="653922989522758100">"很抱歉!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"应用程序 <xliff:g id="APPLICATION">%1$s</xliff:g>(进程:<xliff:g id="PROCESS">%2$s</xliff:g>)意外停止,请重试。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index e72b28e..fe1d78d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -361,10 +361,8 @@
     <string name="permdesc_vibrate" msgid="2886677177257789187">"允許應用程式控制震動。"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"控制閃光燈"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"允許應用程式控制閃光燈。"</string>
-    <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
-    <skip />
-    <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
-    <skip />
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"存取 USB 裝置"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"允許應用程式存取 USB 裝置。"</string>
     <string name="permlab_accessMtp" msgid="4953468676795917042">"執行 MTP 通訊協定"</string>
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"允許存取核心 MTP 驅動程式,以執行 MTP USB 通訊協定。"</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"測試硬體"</string>
@@ -486,8 +484,8 @@
     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"執行重設為原廠設定時,系統會直接清除手機資料而不提出警告"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"設定裝置全域 Proxy"</string>
     <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"設定政策啟用時所要使用的裝置全域 Proxy,只有第一個裝置管理員所設定的全域 Proxy 具有效力。"</string>
-    <string name="policylab_expirePassword" msgid="885279151847254056">"設定螢幕上鎖密碼到期日"</string>
-    <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制螢幕上鎖密碼的變更頻率"</string>
+    <!-- outdated translation 4740941403188940274 -->     <string name="policylab_expirePassword" msgid="885279151847254056">"設定密碼到期日"</string>
+    <!-- outdated translation 6626724939177185949 -->     <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制螢幕鎖定密碼的使用期限"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"設定儲存裝置加密"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"必須為儲存的應用程式資料加密"</string>
   <string-array name="phoneTypes">
@@ -816,8 +814,6 @@
     <string name="alwaysUse" msgid="4583018368000610438">"以此為本操作預設值。"</string>
     <string name="clearDefaultHintMsg" msgid="4815455344600932173">"清除首頁設定 (應用程式) 管理應用程式的預設值。"</string>
     <string name="chooseActivity" msgid="1009246475582238425">"選取一項操作"</string>
-    <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
-    <skip />
     <string name="noApplications" msgid="1691104391758345586">"沒有應用程式可執行此項操作。"</string>
     <string name="aerr_title" msgid="653922989522758100">"很抱歉!"</string>
     <string name="aerr_application" msgid="4683614104336409186">"<xliff:g id="APPLICATION">%1$s</xliff:g> 應用程式 (程序:<xliff:g id="PROCESS">%2$s</xliff:g>) 異常終止。請再試一次。"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b24ee9e..56bc1d3 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -51,6 +51,11 @@
          manager will disable alpha trasformation in animations where not
          strictly needed. -->
     <bool name="config_sf_limitedAlpha">false</bool>
+
+    <!-- Default value used to block data calls if ims is not
+         connected.  If you use the ims apn DCT will block
+         any other apn from connecting until ims apn is connected-->
+    <bool name="ImsConnectedDefaultValue">false</bool>
     
     <!-- Flag indicating whether the surface flinger is inefficient
          at performing a blur.  Used by parts of the UI to turn off
@@ -133,6 +138,9 @@
         <item>"mobile_mms,2,0,2"</item>
         <item>"mobile_supl,3,0,2"</item>
         <item>"mobile_hipri,5,0,3"</item>
+        <item>"mobile_fota,10,0,2"</item>
+        <item>"mobile_ims,11,0,2"</item>
+        <item>"mobile_cbs,12,0,2"</item>
     </string-array>
 
     <!-- This string array should be overridden by the device to present a list of radio
@@ -536,6 +544,9 @@
          which typically is /data/data/com.android.providers.downloads/files -->
     <integer name="config_downloadDataDirSize">100</integer>
 
+    <!-- Max number of downloads allowed to proceed concurrently -->
+    <integer name="config_MaxConcurrentDownloadsAllowed">5</integer>
+
     <!-- When the free space available in DownloadManager's data dir falls
          below the percentage value specified by this param, DownloadManager
          starts removing files to try to make percentage of available
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index e111662..e8e56de 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -16,28 +16,20 @@
 
 package android.text;
 
-import android.graphics.Paint;
+import com.google.android.collect.Lists;
+
+import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextPaint;
-import android.text.TextUtils;
 import android.text.style.StyleSpan;
 import android.text.util.Rfc822Token;
 import android.text.util.Rfc822Tokenizer;
-import android.test.MoreAsserts;
 
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+import java.util.ArrayList;
+import java.util.List;
 
 import junit.framework.TestCase;
 
-import java.util.List;
-import java.util.Map;
-
 /**
  * TextUtilsTest tests {@link TextUtils}.
  */
@@ -354,6 +346,7 @@
             return mString.charAt(off);
         }
 
+        @Override
         public String toString() {
             return mString.toString();
         }
@@ -362,4 +355,104 @@
             return new Wrapper(mString.subSequence(start, end));
         }
     }
+
+    @LargeTest
+    public void testRemoveEmptySpans() {
+        MockSpanned spanned = new MockSpanned();
+
+        spanned.test();
+        spanned.addSpan().test();
+        spanned.addSpan().test();
+        spanned.addSpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addSpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addSpan().test();
+
+        spanned.clear();
+        spanned.addEmptySpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addSpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addSpan().test();
+
+        spanned.clear();
+        spanned.addSpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addSpan().test();
+        spanned.addEmptySpan().test();
+        spanned.addSpan().test();
+        spanned.addSpan().test();
+    }
+
+    protected static class MockSpanned implements Spanned {
+
+        private List<Object> allSpans = new ArrayList<Object>();
+        private List<Object> nonEmptySpans = new ArrayList<Object>();
+
+        public void clear() {
+            allSpans.clear();
+            nonEmptySpans.clear();
+        }
+
+        public MockSpanned addSpan() {
+            Object o = new Object();
+            allSpans.add(o);
+            nonEmptySpans.add(o);
+            return this;
+        }
+
+        public MockSpanned addEmptySpan() {
+            Object o = new Object();
+            allSpans.add(o);
+            return this;
+        }
+
+        public void test() {
+            Object[] nonEmpty = TextUtils.removeEmptySpans(allSpans.toArray(), this, Object.class);
+            assertEquals("Mismatched array size", nonEmptySpans.size(), nonEmpty.length);
+            for (int i=0; i<nonEmpty.length; i++) {
+                assertEquals("Span differ", nonEmptySpans.get(i), nonEmpty[i]);
+            }
+        }
+
+        public char charAt(int arg0) {
+            return 0;
+        }
+
+        public int length() {
+            return 0;
+        }
+
+        public CharSequence subSequence(int arg0, int arg1) {
+            return null;
+        }
+
+        @Override
+        public <T> T[] getSpans(int start, int end, Class<T> type) {
+            return null;
+        }
+
+        @Override
+        public int getSpanStart(Object tag) {
+            return 0;
+        }
+
+        @Override
+        public int getSpanEnd(Object tag) {
+            return nonEmptySpans.contains(tag) ? 1 : 0;
+        }
+
+        @Override
+        public int getSpanFlags(Object tag) {
+            return 0;
+        }
+
+        @Override
+        public int nextSpanTransition(int start, int limit, Class type) {
+            return 0;
+        }
+    }
 }
diff --git a/core/tests/systemproperties/AndroidManifest.xml b/core/tests/systemproperties/AndroidManifest.xml
index ad0abf4..1608788 100644
--- a/core/tests/systemproperties/AndroidManifest.xml
+++ b/core/tests/systemproperties/AndroidManifest.xml
@@ -24,7 +24,7 @@
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
-            android:targetPackage="com.android.frameworks.coretests"
-            android:label="Frameworks Core Tests" />
+            android:targetPackage="com.android.frameworks.coretests.systemproperties"
+            android:label="Frameworks SystemProperties Core Tests" />
 
 </manifest>
diff --git a/core/tests/systemproperties/run_core_systemproperties_test.sh b/core/tests/systemproperties/run_core_systemproperties_test.sh
index 48880f3..d39adbb 100755
--- a/core/tests/systemproperties/run_core_systemproperties_test.sh
+++ b/core/tests/systemproperties/run_core_systemproperties_test.sh
@@ -16,6 +16,9 @@
 if [[ $rebuild == true ]]; then
   make -j4 FrameworksCoreSystemPropertiesTests
   TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreSystemPropertiesTests.apk
+  COMMAND="adb install -r $TESTAPP"
+  echo $COMMAND
+  $COMMAND
 fi
 
 adb shell am instrument -w -e class android.os.SystemPropertiesTest com.android.frameworks.coretests.systemproperties/android.test.InstrumentationTestRunner
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 696e305..e2bfb16 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -621,11 +621,6 @@
 
     remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
 
-    if (NULL != decryptHandle->decryptInfo) {
-        LOGV("deleting decryptInfo");
-        delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
-    }
-    delete decryptHandle; decryptHandle = NULL;
     return reply.readInt32();
 }
 
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index 7b51822..3143d45 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -77,13 +77,14 @@
     return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action);
 }
 
-status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) {
+status_t DrmManagerClient::consumeRights(
+            sp<DecryptHandle> &decryptHandle, int action, bool reserve) {
     Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
 }
 
 status_t DrmManagerClient::setPlaybackStatus(
-            DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+            sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) {
     return mDrmManagerClientImpl
             ->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position);
 }
@@ -117,40 +118,42 @@
     return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray);
 }
 
-DecryptHandle* DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) {
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) {
     return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length);
 }
 
-DecryptHandle* DrmManagerClient::openDecryptSession(const char* uri) {
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(const char* uri) {
     return mDrmManagerClientImpl->openDecryptSession(mUniqueId, uri);
 }
 
-status_t DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) {
+status_t DrmManagerClient::closeDecryptSession(sp<DecryptHandle> &decryptHandle) {
     return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
 }
 
 status_t DrmManagerClient::initializeDecryptUnit(
-            DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
     Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->initializeDecryptUnit(
             mUniqueId, decryptHandle, decryptUnitId, headerInfo);
 }
 
 status_t DrmManagerClient::decrypt(
-    DecryptHandle* decryptHandle, int decryptUnitId,
-    const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
     Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->decrypt(
             mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
 }
 
-status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) {
+status_t DrmManagerClient::finalizeDecryptUnit(
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
     Mutex::Autolock _l(mDecryptLock);
-    return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId);
+    return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId,
+            decryptHandle, decryptUnitId);
 }
 
 ssize_t DrmManagerClient::pread(
-            DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
+            sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
     Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
 }
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index d20de92..e6ae220 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -78,14 +78,16 @@
 }
 
 status_t DrmManagerClientImpl::setOnInfoListener(
-            int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+            int uniqueId,
+            const sp<DrmManagerClient::OnInfoListener>& infoListener) {
     Mutex::Autolock _l(mLock);
     mOnInfoListener = infoListener;
     return getDrmManagerService()->setDrmServiceListener(uniqueId,
             (NULL != infoListener.get()) ? this : NULL);
 }
 
-status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+status_t DrmManagerClientImpl::installDrmEngine(
+        int uniqueId, const String8& drmEngineFile) {
     status_t status = DRM_ERROR_UNKNOWN;
     if (EMPTY_STRING != drmEngineFile) {
         status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile);
@@ -97,7 +99,8 @@
         int uniqueId, const String8* path, const int action) {
     DrmConstraints *drmConstraints = NULL;
     if ((NULL != path) && (EMPTY_STRING != *path)) {
-        drmConstraints = getDrmManagerService()->getConstraints(uniqueId, path, action);
+        drmConstraints =
+            getDrmManagerService()->getConstraints(uniqueId, path, action);
     }
     return drmConstraints;
 }
@@ -110,7 +113,8 @@
     return drmMetadata;
 }
 
-bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+bool DrmManagerClientImpl::canHandle(
+        int uniqueId, const String8& path, const String8& mimeType) {
     bool retCode = false;
     if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
         retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType);
@@ -118,7 +122,8 @@
     return retCode;
 }
 
-DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(
+        int uniqueId, const DrmInfo* drmInfo) {
     DrmInfoStatus *drmInfoStatus = NULL;
     if (NULL != drmInfo) {
         drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo);
@@ -126,7 +131,8 @@
     return drmInfoStatus;
 }
 
-DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+DrmInfo* DrmManagerClientImpl::acquireDrmInfo(
+        int uniqueId, const DrmInfoRequest* drmInfoRequest) {
     DrmInfo* drmInfo = NULL;
     if (NULL != drmInfoRequest) {
         drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest);
@@ -138,12 +144,14 @@
             const String8& rightsPath, const String8& contentPath) {
     status_t status = DRM_ERROR_UNKNOWN;
     if (EMPTY_STRING != contentPath) {
-        status = getDrmManagerService()->saveRights(uniqueId, drmRights, rightsPath, contentPath);
+        status = getDrmManagerService()->saveRights(
+                uniqueId, drmRights, rightsPath, contentPath);
     }
     return status;
 }
 
-String8 DrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path) {
+String8 DrmManagerClientImpl::getOriginalMimeType(
+        int uniqueId, const String8& path) {
     String8 mimeType = EMPTY_STRING;
     if (EMPTY_STRING != path) {
         mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path);
@@ -155,7 +163,8 @@
             int uniqueId, const String8& path, const String8& mimeType) {
     int drmOjectType = DrmObjectType::UNKNOWN;
     if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
-         drmOjectType = getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
+         drmOjectType =
+             getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
     }
     return drmOjectType;
 }
@@ -164,35 +173,41 @@
             int uniqueId, const String8& path, int action) {
     int rightsStatus = RightsStatus::RIGHTS_INVALID;
     if (EMPTY_STRING != path) {
-        rightsStatus = getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
+        rightsStatus =
+            getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
     }
     return rightsStatus;
 }
 
 status_t DrmManagerClientImpl::consumeRights(
-            int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+            int uniqueId, sp<DecryptHandle> &decryptHandle,
+            int action, bool reserve) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
-        status = getDrmManagerService()->consumeRights(uniqueId, decryptHandle, action, reserve);
+    if (NULL != decryptHandle.get()) {
+        status = getDrmManagerService()->consumeRights(
+                uniqueId, decryptHandle.get(), action, reserve);
     }
     return status;
 }
 
 status_t DrmManagerClientImpl::setPlaybackStatus(
-            int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+            int uniqueId, sp<DecryptHandle> &decryptHandle,
+            int playbackStatus, int64_t position) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
+    if (NULL != decryptHandle.get()) {
         status = getDrmManagerService()->setPlaybackStatus(
-                uniqueId, decryptHandle, playbackStatus, position);
+                uniqueId, decryptHandle.get(), playbackStatus, position);
     }
     return status;
 }
 
 bool DrmManagerClientImpl::validateAction(
-            int uniqueId, const String8& path, int action, const ActionDescription& description) {
+            int uniqueId, const String8& path,
+            int action, const ActionDescription& description) {
     bool retCode = false;
     if (EMPTY_STRING != path) {
-        retCode = getDrmManagerService()->validateAction(uniqueId, path, action, description);
+        retCode = getDrmManagerService()->validateAction(
+                uniqueId, path, action, description);
     }
     return retCode;
 }
@@ -209,7 +224,8 @@
     return getDrmManagerService()->removeAllRights(uniqueId);
 }
 
-int DrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+int DrmManagerClientImpl::openConvertSession(
+        int uniqueId, const String8& mimeType) {
     int retCode = INVALID_VALUE;
     if (EMPTY_STRING != mimeType) {
         retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType);
@@ -221,12 +237,14 @@
             int uniqueId, int convertId, const DrmBuffer* inputData) {
     DrmConvertedStatus* drmConvertedStatus = NULL;
     if (NULL != inputData) {
-         drmConvertedStatus = getDrmManagerService()->convertData(uniqueId, convertId, inputData);
+         drmConvertedStatus =
+             getDrmManagerService()->convertData(uniqueId, convertId, inputData);
     }
     return drmConvertedStatus;
 }
 
-DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(
+        int uniqueId, int convertId) {
     return getDrmManagerService()->closeConvertSession(uniqueId, convertId);
 }
 
@@ -234,17 +252,19 @@
             int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
     status_t status = DRM_ERROR_UNKNOWN;
     if ((NULL != drmSupportInfoArray) && (NULL != length)) {
-        status = getDrmManagerService()->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+        status = getDrmManagerService()->getAllSupportInfo(
+                uniqueId, length, drmSupportInfoArray);
     }
     return status;
 }
 
-DecryptHandle* DrmManagerClientImpl::openDecryptSession(
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
             int uniqueId, int fd, off64_t offset, off64_t length) {
     return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length);
 }
 
-DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char* uri) {
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
+        int uniqueId, const char* uri) {
     DecryptHandle* handle = NULL;
     if (NULL != uri) {
         handle = getDrmManagerService()->openDecryptSession(uniqueId, uri);
@@ -252,50 +272,57 @@
     return handle;
 }
 
-status_t DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+status_t DrmManagerClientImpl::closeDecryptSession(
+        int uniqueId, sp<DecryptHandle> &decryptHandle) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
-        status = getDrmManagerService()->closeDecryptSession( uniqueId, decryptHandle);
+    if (NULL != decryptHandle.get()) {
+        status = getDrmManagerService()->closeDecryptSession(
+                uniqueId, decryptHandle.get());
     }
     return status;
 }
 
-status_t DrmManagerClientImpl::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
-            int decryptUnitId, const DrmBuffer* headerInfo) {
+status_t DrmManagerClientImpl::initializeDecryptUnit(
+        int uniqueId, sp<DecryptHandle> &decryptHandle,
+        int decryptUnitId, const DrmBuffer* headerInfo) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if ((NULL != decryptHandle) && (NULL != headerInfo)) {
+    if ((NULL != decryptHandle.get()) && (NULL != headerInfo)) {
         status = getDrmManagerService()->initializeDecryptUnit(
-                uniqueId, decryptHandle, decryptUnitId, headerInfo);
+                uniqueId, decryptHandle.get(), decryptUnitId, headerInfo);
     }
     return status;
 }
 
-status_t DrmManagerClientImpl::decrypt(int uniqueId, DecryptHandle* decryptHandle,
-            int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+status_t DrmManagerClientImpl::decrypt(
+        int uniqueId, sp<DecryptHandle> &decryptHandle,
+        int decryptUnitId, const DrmBuffer* encBuffer,
+        DrmBuffer** decBuffer, DrmBuffer* IV) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if ((NULL != decryptHandle) && (NULL != encBuffer)
+    if ((NULL != decryptHandle.get()) && (NULL != encBuffer)
         && (NULL != decBuffer) && (NULL != *decBuffer)) {
         status = getDrmManagerService()->decrypt(
-                uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+                uniqueId, decryptHandle.get(), decryptUnitId,
+                encBuffer, decBuffer, IV);
     }
     return status;
 }
 
 status_t DrmManagerClientImpl::finalizeDecryptUnit(
-            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+            int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
-        status
-            = getDrmManagerService()->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+    if (NULL != decryptHandle.get()) {
+        status = getDrmManagerService()->finalizeDecryptUnit(
+                    uniqueId, decryptHandle.get(), decryptUnitId);
     }
     return status;
 }
 
-ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle,
+ssize_t DrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
             void* buffer, ssize_t numBytes, off64_t offset) {
     ssize_t retCode = INVALID_VALUE;
-    if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) {
-        retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+    if ((NULL != decryptHandle.get()) && (NULL != buffer) && (0 < numBytes)) {
+        retCode = getDrmManagerService()->pread(
+                uniqueId, decryptHandle.get(), buffer, numBytes, offset);
     }
     return retCode;
 }
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 0a7fcd1..0cba8d4 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -189,7 +189,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+    status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
 
     /**
      * Informs the DRM engine about the playback actions performed on the DRM files.
@@ -203,7 +203,7 @@
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
     status_t setPlaybackStatus(
-            int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+            int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
 
     /**
      * Validates whether an action on the DRM content is allowed or not.
@@ -303,7 +303,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length);
+    sp<DecryptHandle> openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length);
 
     /**
      * Open the decrypt session to decrypt the given protected content
@@ -313,7 +313,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+    sp<DecryptHandle> openDecryptSession(int uniqueId, const char* uri);
 
     /**
      * Close the decrypt session for the given handle
@@ -323,7 +323,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+    status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
 
     /**
      * Initialize decryption for the given unit of the protected content
@@ -335,7 +335,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+    status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
             int decryptUnitId, const DrmBuffer* headerInfo);
 
     /**
@@ -355,7 +355,7 @@
      *     DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
      *     DRM_ERROR_DECRYPT for failure.
      */
-    status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+    status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
             const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
 
     /**
@@ -367,7 +367,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+    status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
 
     /**
      * Reads the specified number of bytes from an open DRM file.
@@ -380,7 +380,7 @@
      *
      * @return Number of bytes read. Returns -1 for Failure.
      */
-    ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+    ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
             void* buffer, ssize_t numBytes, off64_t offset);
 
     /**
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
index 085ebf1..044ff0e 100644
--- a/include/drm/DrmManagerClient.h
+++ b/include/drm/DrmManagerClient.h
@@ -69,7 +69,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(int fd, off64_t offset, off64_t length);
+    sp<DecryptHandle> openDecryptSession(int fd, off64_t offset, off64_t length);
 
     /**
      * Open the decrypt session to decrypt the given protected content
@@ -78,7 +78,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(const char* uri);
+    sp<DecryptHandle> openDecryptSession(const char* uri);
 
     /**
      * Close the decrypt session for the given handle
@@ -87,7 +87,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t closeDecryptSession(DecryptHandle* decryptHandle);
+    status_t closeDecryptSession(sp<DecryptHandle> &decryptHandle);
 
     /**
      * Consumes the rights for a content.
@@ -101,7 +101,7 @@
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure.
      *     In case license has been expired, DRM_ERROR_LICENSE_EXPIRED will be returned.
      */
-    status_t consumeRights(DecryptHandle* decryptHandle, int action, bool reserve);
+    status_t consumeRights(sp<DecryptHandle> &decryptHandle, int action, bool reserve);
 
     /**
      * Informs the DRM engine about the playback actions performed on the DRM files.
@@ -113,7 +113,8 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+    status_t setPlaybackStatus(
+            sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
 
     /**
      * Initialize decryption for the given unit of the protected content
@@ -125,7 +126,7 @@
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
     status_t initializeDecryptUnit(
-            DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
 
     /**
      * Decrypt the protected content buffers for the given unit
@@ -144,7 +145,7 @@
      *     DRM_ERROR_DECRYPT for failure.
      */
     status_t decrypt(
-            DecryptHandle* decryptHandle, int decryptUnitId,
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId,
             const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV = NULL);
 
     /**
@@ -155,7 +156,8 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId);
+    status_t finalizeDecryptUnit(
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId);
 
     /**
      * Reads the specified number of bytes from an open DRM file.
@@ -167,7 +169,8 @@
      *
      * @return Number of bytes read. Returns -1 for Failure.
      */
-    ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset);
+    ssize_t pread(sp<DecryptHandle> &decryptHandle,
+            void* buffer, ssize_t numBytes, off64_t offset);
 
     /**
      * Validates whether an action on the DRM content is allowed or not.
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index 1758cdd..3ad0330 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -19,6 +19,7 @@
 
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Errors.h>
 
@@ -240,7 +241,7 @@
 /**
  * Defines decryption handle
  */
-class DecryptHandle {
+class DecryptHandle : public RefBase {
 public:
     /**
      * Decryption session Handle
@@ -285,10 +286,15 @@
             decryptId(INVALID_VALUE),
             mimeType(""),
             decryptApiType(INVALID_VALUE),
-            status(INVALID_VALUE) {
+            status(INVALID_VALUE),
+            decryptInfo(NULL) {
 
     }
 
+    ~DecryptHandle() {
+        delete decryptInfo; decryptInfo = NULL;
+    }
+
     bool operator<(const DecryptHandle& handle) const {
         return (decryptId < handle.decryptId);
     }
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index e905006..a5cb949 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -47,6 +47,12 @@
     METADATA_KEY_ALBUMARTIST     = 13,
     METADATA_KEY_DISC_NUMBER     = 14,
     METADATA_KEY_COMPILATION     = 15,
+    METADATA_KEY_HAS_AUDIO       = 16,
+    METADATA_KEY_HAS_VIDEO       = 17,
+    METADATA_KEY_VIDEO_WIDTH     = 18,
+    METADATA_KEY_VIDEO_HEIGHT    = 19,
+    METADATA_KEY_BITRATE         = 20,
+
     // Add more here...
 };
 
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index f95e56a..d30e908 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -75,10 +75,10 @@
     static void RegisterDefaultSniffers();
 
     // for DRM
-    virtual DecryptHandle* DrmInitialization() {
+    virtual sp<DecryptHandle> DrmInitialization() {
         return NULL;
     }
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {};
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {};
 
     virtual String8 getUri() {
         return String8();
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index 51a4343..6cf86dc 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -38,9 +38,9 @@
 
     virtual status_t getSize(off64_t *size);
 
-    virtual DecryptHandle* DrmInitialization();
+    virtual sp<DecryptHandle> DrmInitialization();
 
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
 
 protected:
     virtual ~FileSource();
@@ -52,7 +52,7 @@
     Mutex mLock;
 
     /*for DRM*/
-    DecryptHandle *mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
     int64_t mDrmBufOffset;
     int64_t mDrmBufSize;
diff --git a/include/utils/GenerationCache.h b/include/utils/GenerationCache.h
new file mode 100644
index 0000000..bb9ddd6
--- /dev/null
+++ b/include/utils/GenerationCache.h
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_UTILS_GENERATION_CACHE_H
+#define ANDROID_UTILS_GENERATION_CACHE_H
+
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+/**
+ * GenerationCache callback used when an item is removed
+ */
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+    virtual ~OnEntryRemoved() { };
+    virtual void operator()(EntryKey& key, EntryValue& value) = 0;
+}; // class OnEntryRemoved
+
+template<typename EntryKey, typename EntryValue>
+struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
+    Entry() { }
+    Entry(const Entry<EntryKey, EntryValue>& e):
+            key(e.key), value(e.value), parent(e.parent), child(e.child) { }
+    Entry(sp<Entry<EntryKey, EntryValue> > e):
+            key(e->key), value(e->value), parent(e->parent), child(e->child) { }
+
+    EntryKey key;
+    EntryValue value;
+
+    sp<Entry<EntryKey, EntryValue> > parent;
+    sp<Entry<EntryKey, EntryValue> > child;
+}; // struct Entry
+
+/**
+ * A LRU type cache
+ */
+template<typename K, typename V>
+class GenerationCache {
+public:
+    GenerationCache(uint32_t maxCapacity);
+    virtual ~GenerationCache();
+
+    enum Capacity {
+        kUnlimitedCapacity,
+    };
+
+    void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
+
+    void clear();
+
+    bool contains(K key) const;
+    V get(K key);
+    K getKeyAt(uint32_t index) const;
+    bool put(K key, V value);
+    V remove(K key);
+    V removeOldest();
+    V getValueAt(uint32_t index) const;
+
+    uint32_t size() const;
+
+    void addToCache(sp<Entry<K, V> > entry, K key, V value);
+    void attachToCache(sp<Entry<K, V> > entry);
+    void detachFromCache(sp<Entry<K, V> > entry);
+
+    V removeAt(ssize_t index);
+
+private:
+    KeyedVector<K, sp<Entry<K, V> > > mCache;
+    uint32_t mMaxCapacity;
+
+    OnEntryRemoved<K, V>* mListener;
+
+    sp<Entry<K, V> > mOldest;
+    sp<Entry<K, V> > mYoungest;
+}; // class GenerationCache
+
+template<typename K, typename V>
+GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity),
+    mListener(NULL) {
+};
+
+template<typename K, typename V>
+GenerationCache<K, V>::~GenerationCache() {
+    clear();
+};
+
+template<typename K, typename V>
+uint32_t GenerationCache<K, V>::size() const {
+    return mCache.size();
+}
+
+/**
+ * Should be set by the user of the Cache so that the callback is called whenever an item is
+ * removed from the cache
+ */
+template<typename K, typename V>
+void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
+    mListener = listener;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::clear() {
+    if (mListener) {
+        for (uint32_t i = 0; i < mCache.size(); i++) {
+            sp<Entry<K, V> > entry = mCache.valueAt(i);
+            if (mListener) {
+                (*mListener)(entry->key, entry->value);
+            }
+        }
+    }
+    mCache.clear();
+    mYoungest.clear();
+    mOldest.clear();
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::contains(K key) const {
+    return mCache.indexOfKey(key) >= 0;
+}
+
+template<typename K, typename V>
+K GenerationCache<K, V>::getKeyAt(uint32_t index) const {
+    return mCache.keyAt(index);
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::getValueAt(uint32_t index) const {
+    return mCache.valueAt(index)->value;
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::get(K key) {
+    ssize_t index = mCache.indexOfKey(key);
+    if (index >= 0) {
+        sp<Entry<K, V> > entry = mCache.valueAt(index);
+        if (entry.get()) {
+            detachFromCache(entry);
+            attachToCache(entry);
+            return entry->value;
+        }
+    }
+
+    return NULL;
+}
+
+template<typename K, typename V>
+bool GenerationCache<K, V>::put(K key, V value) {
+    if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
+        removeOldest();
+    }
+
+    ssize_t index = mCache.indexOfKey(key);
+    if (index < 0) {
+        sp<Entry<K, V> > entry = new Entry<K, V>;
+        addToCache(entry, key, value);
+        return true;
+    }
+
+    return false;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
+    entry->key = key;
+    entry->value = value;
+    mCache.add(key, entry);
+    attachToCache(entry);
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::remove(K key) {
+    ssize_t index = mCache.indexOfKey(key);
+    if (index >= 0) {
+        return removeAt(index);
+    }
+
+    return NULL;
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::removeAt(ssize_t index) {
+    sp<Entry<K, V> > entry = mCache.valueAt(index);
+    if (mListener) {
+        (*mListener)(entry->key, entry->value);
+    }
+    mCache.removeItemsAt(index, 1);
+    detachFromCache(entry);
+
+    return entry->value;
+}
+
+template<typename K, typename V>
+V GenerationCache<K, V>::removeOldest() {
+    if (mOldest.get()) {
+        ssize_t index = mCache.indexOfKey(mOldest->key);
+        if (index >= 0) {
+            return removeAt(index);
+        }
+    }
+
+    return NULL;
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
+    if (!mYoungest.get()) {
+        mYoungest = mOldest = entry;
+    } else {
+        entry->parent = mYoungest;
+        mYoungest->child = entry;
+        mYoungest = entry;
+    }
+}
+
+template<typename K, typename V>
+void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
+    if (entry->parent.get()) {
+        entry->parent->child = entry->child;
+    }
+
+    if (entry->child.get()) {
+        entry->child->parent = entry->parent;
+    }
+
+    if (mOldest == entry) {
+        mOldest = entry->child;
+    }
+
+    if (mYoungest == entry) {
+        mYoungest = entry->parent;
+    }
+
+    entry->parent.clear();
+    entry->child.clear();
+}
+
+}; // namespace android
+
+#endif // ANDROID_UTILS_GENERATION_CACHE_H
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 77e939e..13e1732 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -398,5 +398,25 @@
      * The metadata key to retrieve the music album compilation status.
      */
     public static final int METADATA_KEY_COMPILATION     = 15;
+    /**
+     * If this key exists the media contains audio content.
+     */
+    public static final int METADATA_KEY_HAS_AUDIO       = 16;
+    /**
+     * If this key exists the media contains video content.
+     */
+    public static final int METADATA_KEY_HAS_VIDEO       = 17;
+    /**
+     * If the media contains video, this key retrieves its width.
+     */
+    public static final int METADATA_KEY_VIDEO_WIDTH     = 18;
+    /**
+     * If the media contains video, this key retrieves its height.
+     */
+    public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
+    /**
+     * This key retrieves the average bitrate (in bits/sec), if available.
+     */
+    public static final int METADATA_KEY_BITRATE         = 20;
     // Add more here...
 }
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 7fb7aed..ca5bc38 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -721,6 +721,9 @@
     createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, &highSpecificTimeLapseProfile);
     profiles->mCamcorderProfiles.add(highTimeLapseProfile);
     profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile);
+
+    // We only have the back-facing camera support by default.
+    profiles->mCameraIds.add(0);
 }
 
 /*static*/ void
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 88069e9..e445b74 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -19,6 +19,7 @@
         ESDS.cpp                          \
         FileSource.cpp                    \
         FLACExtractor.cpp                 \
+        HTTPBase.cpp                      \
         HTTPStream.cpp                    \
         JPEGSource.cpp                    \
         MP3Extractor.cpp                  \
@@ -75,7 +76,7 @@
         libdrmframework  \
         libcrypto        \
         libssl           \
-        libgui
+        libgui           \
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_color_conversion \
@@ -101,6 +102,60 @@
         libstagefright_g711dec \
         libFLAC \
 
+################################################################################
+
+# The following was shamelessly copied from external/webkit/Android.mk and
+# currently must follow the same logic to determine how webkit was built and
+# if it's safe to link against libchromium.net
+
+# V8 also requires an ARMv7 CPU, and since we must use jsc, we cannot
+# use the Chrome http stack either.
+ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true)
+  USE_ALT_HTTP := true
+endif
+
+# See if the user has specified a stack they want to use
+HTTP_STACK = $(HTTP)
+# We default to the Chrome HTTP stack.
+DEFAULT_HTTP = chrome
+ALT_HTTP = android
+
+ifneq ($(HTTP_STACK),chrome)
+  ifneq ($(HTTP_STACK),android)
+    # No HTTP stack is specified, pickup the one we want as default.
+    ifeq ($(USE_ALT_HTTP),true)
+      HTTP_STACK = $(ALT_HTTP)
+    else
+      HTTP_STACK = $(DEFAULT_HTTP)
+    endif
+  endif
+endif
+
+ifeq ($(HTTP_STACK),chrome)
+
+LOCAL_SHARED_LIBRARIES += \
+        liblog           \
+        libicuuc         \
+        libicui18n       \
+        libz             \
+        libdl            \
+
+LOCAL_STATIC_LIBRARIES += \
+        libstagefright_chromium_http \
+        libchromium_net         \
+        libwebcore              \
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+endif
+
+LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
+
+endif  # ifeq ($(HTTP_STACK),chrome)
+
+################################################################################
+
 LOCAL_SHARED_LIBRARIES += \
         libstagefright_amrnb_common \
         libstagefright_enc_common \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 5734c7e..0de1988 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -304,7 +304,7 @@
         return UNKNOWN_ERROR;
     }
 
-    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
     if (mDecryptHandle != NULL) {
         CHECK(mDrmManagerClient);
         if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
@@ -1611,8 +1611,10 @@
 
     if (!strncasecmp("http://", mUri.string(), 7)
             || !strncasecmp("https://", mUri.string(), 8)) {
-        mConnectingDataSource = new NuHTTPDataSource(
-                (mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0);
+        mConnectingDataSource = HTTPBase::Create(
+                (mFlags & INCOGNITO)
+                    ? HTTPBase::kFlagIncognito
+                    : 0);
 
         mLock.unlock();
         status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
@@ -1701,7 +1703,8 @@
         return UNKNOWN_ERROR;
     }
 
-    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+
     if (mDecryptHandle != NULL) {
         CHECK(mDrmManagerClient);
         if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 2809df5..c4ed516 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -41,7 +41,7 @@
 class DRMSource : public MediaSource {
 public:
     DRMSource(const sp<MediaSource> &mediaSource,
-            DecryptHandle *decryptHandle,
+            const sp<DecryptHandle> &decryptHandle,
             DrmManagerClient *managerClient,
             int32_t trackId, DrmBuffer *ipmpBox);
 
@@ -56,7 +56,7 @@
 
 private:
     sp<MediaSource> mOriginalMediaSource;
-    DecryptHandle* mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient* mDrmManagerClient;
     size_t mTrackId;
     mutable Mutex mDRMLock;
@@ -70,7 +70,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
-        DecryptHandle *decryptHandle,
+        const sp<DecryptHandle> &decryptHandle,
         DrmManagerClient *managerClient,
         int32_t trackId, DrmBuffer *ipmpBox)
     : mOriginalMediaSource(mediaSource),
@@ -245,7 +245,7 @@
     mOriginalExtractor->setDrmFlag(true);
     mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
 
-    source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+    source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
 }
 
 DRMExtractor::~DRMExtractor() {
@@ -281,7 +281,7 @@
 bool SniffDRM(
     const sp<DataSource> &source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
-    DecryptHandle *decryptHandle = source->DrmInitialization();
+    sp<DecryptHandle> decryptHandle = source->DrmInitialization();
 
     if (decryptHandle != NULL) {
         if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 3b38208..b5c51f4 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -21,7 +21,7 @@
 #include "include/OggExtractor.h"
 #include "include/MPEG2TSExtractor.h"
 #include "include/NuCachedSource2.h"
-#include "include/NuHTTPDataSource.h"
+#include "include/HTTPBase.h"
 #include "include/DRMExtractor.h"
 #include "include/FLACExtractor.h"
 #include "include/AACExtractor.h"
@@ -127,7 +127,7 @@
         source = new FileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7)
             || !strncasecmp("https://", uri, 8)) {
-        sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource;
+        sp<HTTPBase> httpSource = HTTPBase::Create();
         if (httpSource->connect(uri, headers) != OK) {
             return NULL;
         }
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 02a78c9..f2f3500 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -125,7 +125,7 @@
     return OK;
 }
 
-DecryptHandle* FileSource::DrmInitialization() {
+sp<DecryptHandle> FileSource::DrmInitialization() {
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
@@ -147,8 +147,8 @@
     return mDecryptHandle;
 }
 
-void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
-    *handle = mDecryptHandle;
+void FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+    handle = mDecryptHandle;
 
     *client = mDrmManagerClient;
 }
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
new file mode 100644
index 0000000..58b17a7
--- /dev/null
+++ b/media/libstagefright/HTTPBase.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include "include/HTTPBase.h"
+
+#if CHROMIUM_AVAILABLE
+#include "include/ChromiumHTTPDataSource.h"
+#endif
+
+#include "include/NuHTTPDataSource.h"
+
+#include <cutils/properties.h>
+
+namespace android {
+
+HTTPBase::HTTPBase() {}
+
+// static
+sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
+#if CHROMIUM_AVAILABLE
+    char value[PROPERTY_VALUE_MAX];
+    if (!property_get("media.stagefright.use-chromium", value, NULL)
+            || (strcasecmp("false", value) && strcmp("0", value))) {
+        return new ChromiumHTTPDataSource(flags);
+    } else
+#endif
+    {
+        return new NuHTTPDataSource(flags);
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 7b96d01..1ca2d6d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -262,7 +262,7 @@
 
 MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
     : mDataSource(source),
-      mHaveMetadata(false),
+      mInitCheck(NO_INIT),
       mHasVideo(false),
       mFirstTrack(NULL),
       mLastTrack(NULL),
@@ -361,8 +361,8 @@
 }
 
 status_t MPEG4Extractor::readMetaData() {
-    if (mHaveMetadata) {
-        return OK;
+    if (mInitCheck != NO_INIT) {
+        return mInitCheck;
     }
 
     off64_t offset = 0;
@@ -370,17 +370,20 @@
     while ((err = parseChunk(&offset, 0)) == OK) {
     }
 
-    if (mHaveMetadata) {
+    if (mInitCheck == OK) {
         if (mHasVideo) {
             mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
         } else {
             mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
         }
 
-        return OK;
+        mInitCheck = verifyIfStreamable();
+    } else {
+        mInitCheck = err;
     }
 
-    return err;
+    CHECK_NE(err, (status_t)NO_INIT);
+    return mInitCheck;
 }
 
 void MPEG4Extractor::setDrmFlag(bool flag) {
@@ -755,7 +758,7 @@
                     return err;
                 }
             } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
-                mHaveMetadata = true;
+                mInitCheck = OK;
 
                 if (!mIsDrm) {
                     return UNKNOWN_ERROR;  // Return a dummy error.
@@ -2077,6 +2080,101 @@
     }
 }
 
+MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
+        const char *mimePrefix) {
+    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
+        const char *mime;
+        if (track->meta != NULL
+                && track->meta->findCString(kKeyMIMEType, &mime)
+                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
+            return track;
+        }
+    }
+
+    return NULL;
+}
+
+status_t MPEG4Extractor::verifyIfStreamable() {
+    if (!(mDataSource->flags() & DataSource::kIsCachingDataSource)) {
+        return OK;
+    }
+
+    Track *audio = findTrackByMimePrefix("audio/");
+    Track *video = findTrackByMimePrefix("video/");
+
+    if (audio == NULL || video == NULL) {
+        return OK;
+    }
+
+    sp<SampleTable> audioSamples = audio->sampleTable;
+    sp<SampleTable> videoSamples = video->sampleTable;
+
+    off64_t maxOffsetDiff = 0;
+    int64_t maxOffsetTimeUs = -1;
+
+    for (uint32_t i = 0; i < videoSamples->countSamples(); ++i) {
+        off64_t videoOffset;
+        uint32_t videoTime;
+        bool isSync;
+        CHECK_EQ((status_t)OK, videoSamples->getMetaDataForSample(
+                    i, &videoOffset, NULL, &videoTime, &isSync));
+
+        int64_t videoTimeUs = (int64_t)(videoTime * 1E6 / video->timescale);
+
+        uint32_t reqAudioTime = (videoTimeUs * audio->timescale) / 1000000;
+        uint32_t j;
+        if (audioSamples->findSampleAtTime(
+            reqAudioTime, &j, SampleTable::kFlagClosest) != OK) {
+            continue;
+        }
+
+        off64_t audioOffset;
+        uint32_t audioTime;
+        CHECK_EQ((status_t)OK, audioSamples->getMetaDataForSample(
+                    j, &audioOffset, NULL, &audioTime));
+
+        int64_t audioTimeUs = (int64_t)(audioTime * 1E6 / audio->timescale);
+
+        off64_t offsetDiff = videoOffset - audioOffset;
+        if (offsetDiff < 0) {
+            offsetDiff = -offsetDiff;
+        }
+
+#if 0
+        printf("%s%d/%d videoTime %.2f secs audioTime %.2f secs "
+               "videoOffset %lld audioOffset %lld offsetDiff %lld\n",
+               isSync ? "*" : " ",
+               i,
+               j,
+               videoTimeUs / 1E6,
+               audioTimeUs / 1E6,
+               videoOffset,
+               audioOffset,
+               offsetDiff);
+#endif
+
+        if (offsetDiff > maxOffsetDiff) {
+            maxOffsetDiff = offsetDiff;
+            maxOffsetTimeUs = videoTimeUs;
+        }
+    }
+
+#if 0
+    printf("max offset diff: %lld at video time: %.2f secs\n",
+           maxOffsetDiff, maxOffsetTimeUs / 1E6);
+#endif
+
+    if (maxOffsetDiff < 1024 * 1024) {
+        return OK;
+    }
+
+    LOGE("This content is not streamable, "
+         "max offset diff: %lld at video time: %.2f secs",
+         maxOffsetDiff, maxOffsetTimeUs / 1E6);
+
+    return ERROR_UNSUPPORTED;
+}
+
 static bool LegacySniffMPEG4(
         const sp<DataSource> &source, String8 *mimeType, float *confidence) {
     uint8_t header[8];
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index c7b99b9..7c65612 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -477,11 +477,11 @@
     restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
 }
 
-DecryptHandle* NuCachedSource2::DrmInitialization() {
+sp<DecryptHandle> NuCachedSource2::DrmInitialization() {
     return mSource->DrmInitialization();
 }
 
-void NuCachedSource2::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
+void NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
     mSource->getDrmInfo(handle, client);
 }
 
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index b24343f..73daf12 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -530,7 +530,7 @@
     }
 }
 
-DecryptHandle* NuHTTPDataSource::DrmInitialization() {
+sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
@@ -554,8 +554,8 @@
     return mDecryptHandle;
 }
 
-void NuHTTPDataSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
-    *handle = mDecryptHandle;
+void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+    handle = mDecryptHandle;
 
     *client = mDrmManagerClient;
 }
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index ea3b801..c371cd0 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -411,6 +411,12 @@
 
     mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
 
+    bool hasAudio = false;
+    bool hasVideo = false;
+    int32_t videoWidth = -1;
+    int32_t videoHeight = -1;
+    int32_t audioBitrate = -1;
+
     // The overall duration is the duration of the longest track.
     int64_t maxDurationUs = 0;
     for (size_t i = 0; i < numTracks; ++i) {
@@ -422,12 +428,55 @@
                 maxDurationUs = durationUs;
             }
         }
+
+        const char *mime;
+        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
+            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
+                hasAudio = true;
+
+                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
+                    audioBitrate = -1;
+                }
+            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
+                hasVideo = true;
+
+                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
+                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
+            }
+        }
     }
 
     // The duration value is a string representing the duration in ms.
     sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
     mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
 
+    if (hasAudio) {
+        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
+    }
+
+    if (hasVideo) {
+        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
+
+        sprintf(tmp, "%d", videoWidth);
+        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
+
+        sprintf(tmp, "%d", videoHeight);
+        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
+    }
+
+    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
+        sprintf(tmp, "%ld", audioBitrate);
+        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+    } else {
+        off64_t sourceSize;
+        if (mSource->getSize(&sourceSize) == OK) {
+            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
+
+            sprintf(tmp, "%lld", avgBitRate);
+            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+        }
+    }
+
     if (numTracks == 1) {
         const char *fileMIME;
         CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
new file mode 100644
index 0000000..80b2478
--- /dev/null
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=       \
+        ChromiumHTTPDataSource.cpp        \
+        support.cpp                     \
+
+LOCAL_C_INCLUDES:= \
+        $(JNI_H_INCLUDE) \
+        frameworks/base/media/libstagefright \
+        $(TOP)/frameworks/base/include/media/stagefright/openmax \
+        external/chromium \
+        external/chromium/android
+
+LOCAL_CFLAGS += -Wno-multichar
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+endif
+
+LOCAL_MODULE:= libstagefright_chromium_http
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
new file mode 100644
index 0000000..949a5e4
--- /dev/null
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSource"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include "support.h"
+
+namespace android {
+
+ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
+    : mFlags(flags),
+      mState(DISCONNECTED),
+      mDelegate(new SfDelegate),
+      mCurrentOffset(0),
+      mIOResult(OK),
+      mContentSize(-1),
+      mNumBandwidthHistoryItems(0),
+      mTotalTransferTimeUs(0),
+      mTotalTransferBytes(0),
+      mDecryptHandle(NULL),
+      mDrmManagerClient(NULL) {
+    mDelegate->setOwner(this);
+}
+
+ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
+    disconnect();
+
+    delete mDelegate;
+    mDelegate = NULL;
+
+    if (mDrmManagerClient != NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+}
+
+status_t ChromiumHTTPDataSource::connect(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    Mutex::Autolock autoLock(mLock);
+
+    return connect_l(uri, headers, offset);
+}
+
+status_t ChromiumHTTPDataSource::connect_l(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    if (mState != DISCONNECTED) {
+        disconnect_l();
+    }
+
+    if (!(mFlags & kFlagIncognito)) {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
+    } else {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
+                "connect to <URL suppressed> @%lld", offset);
+    }
+
+    mURI = uri;
+
+    if (headers != NULL) {
+        mHeaders = *headers;
+    } else {
+        mHeaders.clear();
+    }
+
+    mState = CONNECTING;
+    mContentSize = -1;
+    mCurrentOffset = offset;
+
+    mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
+
+    while (mState == CONNECTING) {
+        mCondition.wait(mLock);
+    }
+
+    return mState == CONNECTED ? OK : mIOResult;
+}
+
+void ChromiumHTTPDataSource::onConnectionEstablished(int64_t contentSize) {
+    Mutex::Autolock autoLock(mLock);
+    mState = CONNECTED;
+    mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+    mCondition.broadcast();
+}
+
+void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
+    Mutex::Autolock autoLock(mLock);
+    mState = DISCONNECTED;
+    mCondition.broadcast();
+
+    mURI.clear();
+
+    mIOResult = err;
+
+    clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::disconnect() {
+    Mutex::Autolock autoLock(mLock);
+    disconnect_l();
+}
+
+void ChromiumHTTPDataSource::disconnect_l() {
+    if (mState == DISCONNECTED) {
+        return;
+    }
+
+    mState = DISCONNECTING;
+    mIOResult = -EINTR;
+
+    mDelegate->initiateDisconnect();
+
+    while (mState == DISCONNECTING) {
+        mCondition.wait(mLock);
+    }
+
+    CHECK_EQ((int)mState, (int)DISCONNECTED);
+}
+
+status_t ChromiumHTTPDataSource::initCheck() const {
+    Mutex::Autolock autoLock(mLock);
+
+    return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mState != CONNECTED) {
+        return ERROR_NOT_CONNECTED;
+    }
+
+    if (offset != mCurrentOffset) {
+        AString tmp = mURI;
+        KeyedVector<String8, String8> tmpHeaders = mHeaders;
+
+        disconnect_l();
+
+        status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    mState = READING;
+
+    int64_t startTimeUs = ALooper::GetNowUs();
+
+    mDelegate->initiateRead(data, size);
+
+    while (mState == READING) {
+        mCondition.wait(mLock);
+    }
+
+    if (mIOResult < OK) {
+        return mIOResult;
+    }
+
+    if (mState == CONNECTED) {
+        int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+        // The read operation was successful, mIOResult contains
+        // the number of bytes read.
+        addBandwidthMeasurement_l(mIOResult, delayUs);
+
+        mCurrentOffset += mIOResult;
+        return mIOResult;
+    }
+
+    return ERROR_IO;
+}
+
+void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    mIOResult = size;
+
+    if (mState == READING) {
+        mState = CONNECTED;
+        mCondition.broadcast();
+    }
+}
+
+status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mContentSize < 0) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    *size = mContentSize;
+
+    return OK;
+}
+
+uint32_t ChromiumHTTPDataSource::flags() {
+    return kWantsPrefetching;
+}
+
+// static
+void ChromiumHTTPDataSource::InitiateRead(
+        ChromiumHTTPDataSource *me, void *data, size_t size) {
+    me->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
+    mDelegate->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::onDisconnectComplete() {
+    Mutex::Autolock autoLock(mLock);
+    CHECK_EQ((int)mState, (int)DISCONNECTING);
+
+    mState = DISCONNECTED;
+    mURI.clear();
+
+    mCondition.broadcast();
+
+    clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::addBandwidthMeasurement_l(
+        size_t numBytes, int64_t delayUs) {
+    BandwidthEntry entry;
+    entry.mDelayUs = delayUs;
+    entry.mNumBytes = numBytes;
+    mTotalTransferTimeUs += delayUs;
+    mTotalTransferBytes += numBytes;
+
+    mBandwidthHistory.push_back(entry);
+    if (++mNumBandwidthHistoryItems > 100) {
+        BandwidthEntry *entry = &*mBandwidthHistory.begin();
+        mTotalTransferTimeUs -= entry->mDelayUs;
+        mTotalTransferBytes -= entry->mNumBytes;
+        mBandwidthHistory.erase(mBandwidthHistory.begin());
+        --mNumBandwidthHistoryItems;
+    }
+}
+
+bool ChromiumHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mNumBandwidthHistoryItems < 2) {
+        return false;
+    }
+
+    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+    return true;
+}
+
+sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mDrmManagerClient == NULL) {
+        mDrmManagerClient = new DrmManagerClient();
+    }
+
+    if (mDrmManagerClient == NULL) {
+        return NULL;
+    }
+
+    if (mDecryptHandle == NULL) {
+        /* Note if redirect occurs, mUri is the redirect uri instead of the
+         * original one
+         */
+        mDecryptHandle = mDrmManagerClient->openDecryptSession(
+                String8(mURI.c_str()));
+    }
+
+    if (mDecryptHandle == NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+
+    return mDecryptHandle;
+}
+
+void ChromiumHTTPDataSource::getDrmInfo(
+        sp<DecryptHandle> &handle, DrmManagerClient **client) {
+    Mutex::Autolock autoLock(mLock);
+
+    handle = mDecryptHandle;
+    *client = mDrmManagerClient;
+}
+
+String8 ChromiumHTTPDataSource::getUri() {
+    Mutex::Autolock autoLock(mLock);
+
+    return String8(mURI.c_str());
+}
+
+void ChromiumHTTPDataSource::clearDRMState_l() {
+    if (mDecryptHandle != NULL) {
+        // To release mDecryptHandle
+        CHECK(mDrmManagerClient);
+        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+        mDecryptHandle = NULL;
+    }
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
new file mode 100644
index 0000000..7ac56e8
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSourceSupport"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+#include "support.h"
+
+#include "android/net/android_network_library_impl.h"
+#include "base/thread.h"
+#include "net/base/host_resolver.h"
+#include "net/base/ssl_config_service.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/proxy/proxy_config_service_android.h"
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+static Mutex gNetworkThreadLock;
+static base::Thread *gNetworkThread = NULL;
+static scoped_refptr<URLRequestContext> gReqContext;
+
+static void InitializeNetworkThreadIfNecessary() {
+    Mutex::Autolock autoLock(gNetworkThreadLock);
+    if (gNetworkThread == NULL) {
+        gNetworkThread = new base::Thread("network");
+        base::Thread::Options options;
+        options.message_loop_type = MessageLoop::TYPE_IO;
+        CHECK(gNetworkThread->StartWithOptions(options));
+
+        gReqContext = new SfRequestContext;
+
+        net::AndroidNetworkLibrary::RegisterSharedInstance(
+                new SfNetworkLibrary);
+    }
+}
+
+static void MY_LOGI(const char *s) {
+    LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
+}
+
+static void MY_LOGV(const char *s) {
+#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
+    LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
+#endif
+}
+
+SfNetLog::SfNetLog()
+    : mNextID(1) {
+}
+
+void SfNetLog::AddEntry(
+        EventType type,
+        const base::TimeTicks &time,
+        const Source &source,
+        EventPhase phase,
+        EventParameters *params) {
+#if 0
+    MY_LOGI(StringPrintf(
+                "AddEntry time=%s type=%s source=%s phase=%s\n",
+                TickCountToString(time).c_str(),
+                EventTypeToString(type),
+                SourceTypeToString(source.type),
+                EventPhaseToString(phase)).c_str());
+#endif
+}
+
+uint32 SfNetLog::NextID() {
+    return mNextID++;
+}
+
+net::NetLog::LogLevel SfNetLog::GetLogLevel() const {
+    return LOG_ALL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfRequestContext::SfRequestContext() {
+    AString ua;
+    ua.append("stagefright/1.2 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    ua.append(value);
+    ua.append(")");
+
+    mUserAgent = ua.c_str();
+
+    net_log_ = new SfNetLog;
+
+    host_resolver_ =
+        net::CreateSystemHostResolver(
+                net::HostResolver::kDefaultParallelism,
+                NULL /* resolver_proc */,
+                net_log_);
+
+    ssl_config_service_ =
+        net::SSLConfigService::CreateSystemSSLConfigService();
+
+    proxy_service_ = net::ProxyService::CreateWithoutProxyResolver(
+            new net::ProxyConfigServiceAndroid, net_log_);
+
+    http_transaction_factory_ = new net::HttpCache(
+            host_resolver_,
+            dnsrr_resolver_,
+            dns_cert_checker_.get(),
+            proxy_service_.get(),
+            ssl_config_service_.get(),
+            net::HttpAuthHandlerFactory::CreateDefault(host_resolver_),
+            network_delegate_,
+            net_log_,
+            NULL);  // backend_factory
+}
+
+const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
+    return mUserAgent;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfNetworkLibrary::SfNetworkLibrary() {}
+
+SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
+        const std::vector<std::string>& cert_chain,
+        const std::string& hostname,
+        const std::string& auth_type) {
+    return VERIFY_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfDelegate::SfDelegate()
+    : mOwner(NULL),
+      mURLRequest(NULL),
+      mReadBuffer(new net::IOBufferWithSize(8192)),
+      mNumBytesRead(0),
+      mNumBytesTotal(0),
+      mDataDestination(NULL),
+      mAtEOS(false) {
+    InitializeNetworkThreadIfNecessary();
+}
+
+SfDelegate::~SfDelegate() {
+    CHECK(mURLRequest == NULL);
+}
+
+void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
+    mOwner = owner;
+}
+
+void SfDelegate::OnReceivedRedirect(
+            URLRequest *request, const GURL &new_url, bool *defer_redirect) {
+    MY_LOGI("OnReceivedRedirect");
+}
+
+void SfDelegate::OnAuthRequired(
+            URLRequest *request, net::AuthChallengeInfo *auth_info) {
+    MY_LOGI("OnAuthRequired");
+
+    inherited::OnAuthRequired(request, auth_info);
+}
+
+void SfDelegate::OnCertificateRequested(
+            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) {
+    fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
+
+    inherited::OnSSLCertificateError(request, cert_error, cert);
+}
+
+void SfDelegate::OnGetCookies(URLRequest *request, bool blocked_by_policy) {
+    MY_LOGI("OnGetCookies");
+}
+
+void SfDelegate::OnSetCookie(
+        URLRequest *request,
+        const std::string &cookie_line,
+        const net::CookieOptions &options,
+        bool blocked_by_policy) {
+    MY_LOGI("OnSetCookie");
+}
+
+void SfDelegate::OnResponseStarted(URLRequest *request) {
+    if (request->status().status() != URLRequestStatus::SUCCESS) {
+        MY_LOGI(StringPrintf(
+                    "Request failed with status %d and os_error %d",
+                    request->status().status(),
+                    request->status().os_error()).c_str());
+
+        delete mURLRequest;
+        mURLRequest = NULL;
+
+        mOwner->onConnectionFailed(ERROR_IO);
+        return;
+    } else if (mRangeRequested && request->GetResponseCode() != 206) {
+        MY_LOGI(StringPrintf(
+                    "We requested a content range, but server didn't "
+                    "support that. (responded with %d)",
+                    request->GetResponseCode()).c_str());
+
+        delete mURLRequest;
+        mURLRequest = NULL;
+
+        mOwner->onConnectionFailed(-EPIPE);
+        return;
+    } else if ((request->GetResponseCode() / 100) != 2) {
+        MY_LOGI(StringPrintf(
+                    "Server responded with http status %d",
+                    request->GetResponseCode()).c_str());
+
+        delete mURLRequest;
+        mURLRequest = NULL;
+
+        mOwner->onConnectionFailed(ERROR_IO);
+        return;
+    }
+
+    MY_LOGV("OnResponseStarted");
+
+    std::string headers;
+    request->GetAllResponseHeaders(&headers);
+
+    MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
+
+    mOwner->onConnectionEstablished(request->GetExpectedContentSize());
+}
+
+void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) {
+    if (bytes_read == -1) {
+        MY_LOGI(StringPrintf(
+                    "OnReadCompleted, read failed, status %d",
+                    request->status().status()).c_str());
+
+        mOwner->onReadCompleted(ERROR_IO);
+        return;
+    }
+
+    MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
+
+    if (bytes_read < 0) {
+        MY_LOGI(StringPrintf(
+                    "Read failed w/ status %d\n",
+                    request->status().status()).c_str());
+
+        mOwner->onReadCompleted(ERROR_IO);
+        return;
+    } else if (bytes_read == 0) {
+        mAtEOS = true;
+        mOwner->onReadCompleted(mNumBytesRead);
+        return;
+    }
+
+    CHECK_GT(bytes_read, 0);
+    CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
+
+    memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+           mReadBuffer->data(),
+           bytes_read);
+
+    mNumBytesRead += bytes_read;
+
+    readMore(request);
+}
+
+void SfDelegate::readMore(URLRequest *request) {
+    while (mNumBytesRead < mNumBytesTotal) {
+        size_t copy = mNumBytesTotal - mNumBytesRead;
+        if (copy > mReadBuffer->size()) {
+            copy = mReadBuffer->size();
+        }
+
+        int n;
+        if (request->Read(mReadBuffer, copy, &n)) {
+            MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
+
+            CHECK_LE((size_t)n, copy);
+
+            memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+                   mReadBuffer->data(),
+                   n);
+
+            mNumBytesRead += n;
+
+            if (n == 0) {
+                mAtEOS = true;
+                break;
+            }
+        } else {
+            MY_LOGV("readMore pending read");
+
+            if (request->status().status() != URLRequestStatus::IO_PENDING) {
+                MY_LOGI(StringPrintf(
+                            "Direct read failed w/ status %d\n",
+                            request->status().status()).c_str());
+
+                mOwner->onReadCompleted(ERROR_IO);
+                return;
+            }
+
+            return;
+        }
+    }
+
+    mOwner->onReadCompleted(mNumBytesRead);
+}
+
+void SfDelegate::initiateConnection(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    GURL url(uri);
+
+    MessageLoop *loop = gNetworkThread->message_loop();
+    loop->PostTask(
+            FROM_HERE,
+            NewRunnableFunction(
+                &SfDelegate::OnInitiateConnectionWrapper,
+                this,
+                url,
+                headers,
+                offset));
+
+}
+
+// static
+void SfDelegate::OnInitiateConnectionWrapper(
+        SfDelegate *me, GURL url,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    me->onInitiateConnection(url, headers, offset);
+}
+
+void SfDelegate::onInitiateConnection(
+        const GURL &url,
+        const KeyedVector<String8, String8> *extra,
+        off64_t offset) {
+    CHECK(mURLRequest == NULL);
+
+    mURLRequest = new URLRequest(url, this);
+    mAtEOS = false;
+
+    mRangeRequested = false;
+
+    if (offset != 0 || extra != NULL) {
+        net::HttpRequestHeaders headers =
+            mURLRequest->extra_request_headers();
+
+        if (offset != 0) {
+            headers.AddHeaderFromString(
+                    StringPrintf("Range: bytes=%lld-", offset).c_str());
+
+            mRangeRequested = true;
+        }
+
+        if (extra != NULL) {
+            for (size_t i = 0; i < extra->size(); ++i) {
+                AString s;
+                s.append(extra->keyAt(i).string());
+                s.append(": ");
+                s.append(extra->valueAt(i).string());
+
+                headers.AddHeaderFromString(s.c_str());
+            }
+        }
+
+        mURLRequest->SetExtraRequestHeaders(headers);
+    }
+
+    mURLRequest->set_context(gReqContext);
+
+    mURLRequest->Start();
+}
+
+void SfDelegate::initiateDisconnect() {
+    MessageLoop *loop = gNetworkThread->message_loop();
+    loop->PostTask(
+            FROM_HERE,
+            NewRunnableFunction(
+                &SfDelegate::OnInitiateDisconnectWrapper, this));
+}
+
+// static
+void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
+    me->onInitiateDisconnect();
+}
+
+void SfDelegate::onInitiateDisconnect() {
+    mURLRequest->Cancel();
+
+    delete mURLRequest;
+    mURLRequest = NULL;
+
+    mOwner->onDisconnectComplete();
+}
+
+void SfDelegate::initiateRead(void *data, size_t size) {
+    MessageLoop *loop = gNetworkThread->message_loop();
+    loop->PostTask(
+            FROM_HERE,
+            NewRunnableFunction(
+                &SfDelegate::OnInitiateReadWrapper, this, data, size));
+}
+
+// static
+void SfDelegate::OnInitiateReadWrapper(
+        SfDelegate *me, void *data, size_t size) {
+    me->onInitiateRead(data, size);
+}
+
+void SfDelegate::onInitiateRead(void *data, size_t size) {
+    CHECK(mURLRequest != NULL);
+
+    mNumBytesRead = 0;
+    mNumBytesTotal = size;
+    mDataDestination = data;
+
+    if (mAtEOS) {
+        mOwner->onReadCompleted(0);
+        return;
+    }
+
+    readMore(mURLRequest);
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
new file mode 100644
index 0000000..634ac93
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.h
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+#ifndef SUPPORT_H_
+
+#define SUPPORT_H_
+
+#include <assert.h>
+
+#include "net/base/net_log.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/base/android_network_library.h"
+#include "net/base/io_buffer.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct SfNetLog : public net::NetLog {
+    SfNetLog();
+
+    virtual void AddEntry(
+            EventType type,
+            const base::TimeTicks &time,
+            const Source &source,
+            EventPhase phase,
+            EventParameters *params);
+
+    virtual uint32 NextID();
+    virtual LogLevel GetLogLevel() const;
+
+private:
+    uint32 mNextID;
+
+    DISALLOW_EVIL_CONSTRUCTORS(SfNetLog);
+};
+
+struct SfRequestContext : public URLRequestContext {
+    SfRequestContext();
+
+    virtual const std::string &GetUserAgent(const GURL &url) const;
+
+private:
+    std::string mUserAgent;
+
+    DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext);
+};
+
+// This is required for https support, we don't really verify certificates,
+// we accept anything...
+struct SfNetworkLibrary : public net::AndroidNetworkLibrary {
+    SfNetworkLibrary();
+
+    virtual VerifyResult VerifyX509CertChain(
+            const std::vector<std::string>& cert_chain,
+            const std::string& hostname,
+            const std::string& auth_type);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(SfNetworkLibrary);
+};
+
+struct ChromiumHTTPDataSource;
+
+struct SfDelegate : public URLRequest::Delegate {
+    SfDelegate();
+    virtual ~SfDelegate();
+
+    void initiateConnection(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    void initiateDisconnect();
+    void initiateRead(void *data, size_t size);
+
+    void setOwner(ChromiumHTTPDataSource *mOwner);
+
+    virtual void OnReceivedRedirect(
+            URLRequest *request, const GURL &new_url, bool *defer_redirect);
+
+    virtual void OnAuthRequired(
+            URLRequest *request, net::AuthChallengeInfo *auth_info);
+
+    virtual void OnCertificateRequested(
+            URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
+
+    virtual void OnSSLCertificateError(
+            URLRequest *request, int cert_error, net::X509Certificate *cert);
+
+    virtual void OnGetCookies(URLRequest *request, bool blocked_by_policy);
+
+    virtual void OnSetCookie(
+            URLRequest *request,
+            const std::string &cookie_line,
+            const net::CookieOptions &options,
+            bool blocked_by_policy);
+
+    virtual void OnResponseStarted(URLRequest *request);
+
+    virtual void OnReadCompleted(URLRequest *request, int bytes_read);
+
+private:
+    typedef Delegate inherited;
+
+    ChromiumHTTPDataSource *mOwner;
+
+    URLRequest *mURLRequest;
+    scoped_refptr<net::IOBufferWithSize> mReadBuffer;
+
+    size_t mNumBytesRead;
+    size_t mNumBytesTotal;
+    void *mDataDestination;
+
+    bool mRangeRequested;
+    bool mAtEOS;
+
+    void readMore(URLRequest *request);
+
+    static void OnInitiateConnectionWrapper(
+            SfDelegate *me,
+            GURL url,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    static void OnInitiateDisconnectWrapper(SfDelegate *me);
+
+    static void OnInitiateReadWrapper(
+            SfDelegate *me, void *data, size_t size);
+
+    void onInitiateConnection(
+            const GURL &url,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    void onInitiateDisconnect();
+    void onInitiateRead(void *data, size_t size);
+
+    DISALLOW_EVIL_CONSTRUCTORS(SfDelegate);
+};
+
+}  // namespace android
+
+#endif  // SUPPORT_H_
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index f0cd6a0..8e1bdf3 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -23,7 +23,7 @@
 #include "LiveDataSource.h"
 
 #include "include/M3UParser.h"
-#include "include/NuHTTPDataSource.h"
+#include "include/HTTPBase.h"
 
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/hexdump.h>
@@ -45,9 +45,9 @@
     : mFlags(flags),
       mDataSource(new LiveDataSource),
       mHTTPDataSource(
-              new NuHTTPDataSource(
+              HTTPBase::Create(
                   (mFlags & kFlagIncognito)
-                    ? NuHTTPDataSource::kFlagIncognito
+                    ? HTTPBase::kFlagIncognito
                     : 0)),
       mPrevBandwidthIndex(-1),
       mLastPlaylistFetchTimeUs(-1),
@@ -625,7 +625,12 @@
     } else {
         key = new ABuffer(16);
 
-        sp<NuHTTPDataSource> keySource = new NuHTTPDataSource;
+        sp<HTTPBase> keySource =
+              HTTPBase::Create(
+                  (mFlags & kFlagIncognito)
+                    ? HTTPBase::kFlagIncognito
+                    : 0);
+
         status_t err = keySource->connect(keyURI.c_str());
 
         if (err == OK) {
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 4e6f75c..b26f202 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -18,7 +18,7 @@
 
 #define AWESOME_PLAYER_H_
 
-#include "NuHTTPDataSource.h"
+#include "HTTPBase.h"
 #include "TimedEventQueue.h"
 
 #include <media/MediaPlayerInterface.h>
@@ -209,7 +209,7 @@
 
     MediaBuffer *mVideoBuffer;
 
-    sp<NuHTTPDataSource> mConnectingDataSource;
+    sp<HTTPBase> mConnectingDataSource;
     sp<NuCachedSource2> mCachedSource;
 
     sp<ALooper> mLooper;
@@ -217,7 +217,7 @@
     sp<ARTSPController> mConnectingRTSPController;
 
     DrmManagerClient *mDrmManagerClient;
-    DecryptHandle *mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
 
     status_t setDataSource_l(
             const char *uri,
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
new file mode 100644
index 0000000..af49059
--- /dev/null
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#ifndef CHROME_HTTP_DATA_SOURCE_H_
+
+#define CHROME_HTTP_DATA_SOURCE_H_
+
+#include <media/stagefright/foundation/AString.h>
+#include <utils/threads.h>
+
+#include "HTTPBase.h"
+
+namespace android {
+
+struct SfDelegate;
+
+struct ChromiumHTTPDataSource : public HTTPBase {
+    ChromiumHTTPDataSource(uint32_t flags = 0);
+
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            off64_t offset = 0);
+
+    virtual void disconnect();
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+    virtual status_t getSize(off64_t *size);
+    virtual uint32_t flags();
+
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps);
+
+    virtual sp<DecryptHandle> DrmInitialization();
+
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
+
+    virtual String8 getUri();
+
+protected:
+    virtual ~ChromiumHTTPDataSource();
+
+private:
+    friend struct SfDelegate;
+
+    enum State {
+        DISCONNECTED,
+        CONNECTING,
+        CONNECTED,
+        READING,
+        DISCONNECTING
+    };
+
+    struct BandwidthEntry {
+        int64_t mDelayUs;
+        size_t mNumBytes;
+    };
+
+    const uint32_t mFlags;
+
+    mutable Mutex mLock;
+    Condition mCondition;
+
+    State mState;
+
+    SfDelegate *mDelegate;
+
+    AString mURI;
+    KeyedVector<String8, String8> mHeaders;
+
+    off64_t mCurrentOffset;
+
+    // Any connection error or the result of a read operation
+    // (for the lattter this is the number of bytes read, if successful).
+    ssize_t mIOResult;
+
+    int64_t mContentSize;
+
+    List<BandwidthEntry> mBandwidthHistory;
+    size_t mNumBandwidthHistoryItems;
+    int64_t mTotalTransferTimeUs;
+    size_t mTotalTransferBytes;
+
+    sp<DecryptHandle> mDecryptHandle;
+    DrmManagerClient *mDrmManagerClient;
+
+    void disconnect_l();
+
+    status_t connect_l(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    static void InitiateRead(
+            ChromiumHTTPDataSource *me, void *data, size_t size);
+
+    void initiateRead(void *data, size_t size);
+
+    void onConnectionEstablished(int64_t contentSize);
+    void onConnectionFailed(status_t err);
+    void onReadCompleted(ssize_t size);
+    void onDisconnectComplete();
+
+    void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs);
+
+    void clearDRMState_l();
+
+    DISALLOW_EVIL_CONSTRUCTORS(ChromiumHTTPDataSource);
+};
+
+}  // namespace android
+
+#endif  // CHROME_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
index 9881cc1..b4e4afb 100644
--- a/media/libstagefright/include/DRMExtractor.h
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -45,7 +45,7 @@
     sp<DataSource> mDataSource;
 
     sp<MediaExtractor> mOriginalExtractor;
-    DecryptHandle* mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient* mDrmManagerClient;
 
     DRMExtractor(const DRMExtractor &);
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
new file mode 100644
index 0000000..6cec390
--- /dev/null
+++ b/media/libstagefright/include/HTTPBase.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#ifndef HTTP_BASE_H_
+
+#define HTTP_BASE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+struct HTTPBase : public DataSource {
+    enum Flags {
+        // Don't log any URLs.
+        kFlagIncognito = 1
+    };
+
+    HTTPBase();
+
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            off64_t offset = 0) = 0;
+
+    virtual void disconnect() = 0;
+
+    // Returns true if bandwidth could successfully be estimated,
+    // false otherwise.
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps) = 0;
+
+    static sp<HTTPBase> Create(uint32_t flags = 0);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
+};
+
+}  // namespace android
+
+#endif  // HTTP_BASE_H_
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 3fe5d4e..2b5ea0e 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -26,7 +26,7 @@
 struct DataSource;
 struct LiveDataSource;
 struct M3UParser;
-struct NuHTTPDataSource;
+struct HTTPBase;
 
 struct LiveSession : public AHandler {
     enum Flags {
@@ -75,7 +75,7 @@
 
     sp<LiveDataSource> mDataSource;
 
-    sp<NuHTTPDataSource> mHTTPDataSource;
+    sp<HTTPBase> mHTTPDataSource;
 
     AString mMasterURL;
     Vector<BandwidthItem> mBandwidthItems;
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 04e8a6a..d9ef208 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -57,7 +57,7 @@
     };
 
     sp<DataSource> mDataSource;
-    bool mHaveMetadata;
+    status_t mInitCheck;
     bool mHasVideo;
 
     Track *mFirstTrack, *mLastTrack;
@@ -90,6 +90,10 @@
 
     status_t parseTrackHeader(off64_t data_offset, off64_t data_size);
 
+    Track *findTrackByMimePrefix(const char *mimePrefix);
+
+    status_t verifyIfStreamable();
+
     MPEG4Extractor(const MPEG4Extractor &);
     MPEG4Extractor &operator=(const MPEG4Extractor &);
 };
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 022804c..02d5817 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -37,8 +37,8 @@
     virtual status_t getSize(off64_t *size);
     virtual uint32_t flags();
 
-    virtual DecryptHandle* DrmInitialization();
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+    virtual sp<DecryptHandle> DrmInitialization();
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
     virtual String8 getUri();
     ////////////////////////////////////////////////////////////////////////////
 
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 2569568..7dd5d59 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -18,28 +18,24 @@
 
 #define NU_HTTP_DATA_SOURCE_H_
 
-#include <media/stagefright/DataSource.h>
 #include <utils/List.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 
 #include "HTTPStream.h"
+#include "include/HTTPBase.h"
 
 namespace android {
 
-struct NuHTTPDataSource : public DataSource {
-    enum Flags {
-        // Don't log any URLs.
-        kFlagIncognito = 1
-    };
+struct NuHTTPDataSource : public HTTPBase {
     NuHTTPDataSource(uint32_t flags = 0);
 
-    status_t connect(
+    virtual status_t connect(
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL,
             off64_t offset = 0);
 
-    void disconnect();
+    virtual void disconnect();
 
     virtual status_t initCheck() const;
 
@@ -49,10 +45,10 @@
 
     // Returns true if bandwidth could successfully be estimated,
     // false otherwise.
-    bool estimateBandwidth(int32_t *bandwidth_bps);
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps);
 
-    virtual DecryptHandle* DrmInitialization();
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+    virtual sp<DecryptHandle> DrmInitialization();
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
     virtual String8 getUri();
 
 protected:
@@ -98,7 +94,7 @@
     int64_t mTotalTransferTimeUs;
     size_t mTotalTransferBytes;
 
-    DecryptHandle *mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
 
     status_t connect(
diff --git a/opengl/libagl2/Android.mk b/opengl/libagl2/Android.mk
new file mode 100644
index 0000000..564932f
--- /dev/null
+++ b/opengl/libagl2/Android.mk
@@ -0,0 +1,58 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# Build the software OpenGL ES library
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	src/api.cpp \
+	src/egl.cpp \
+    src/get.cpp \
+	src/shader.cpp \
+	src/state.cpp \
+	src/texture.cpp \
+	src/vertex.cpp
+
+LOCAL_C_INCLUDES :=	\
+    $(LOCAL_PATH) \
+    external/mesa3d/include \
+    external/mesa3d/src \
+    external/stlport/stlport \
+    bionic
+    
+#LOCAL_CFLAGS += -DLOG_TAG=\"libagl2\"
+#LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+#LOCAL_CFLAGS += -fvisibility=hidden
+#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
+LOCAL_CFLAGS += -O3
+LOCAL_STATIC_LIBRARIES := libMesa
+LOCAL_SHARED_LIBRARIES := libstlport libcutils libhardware libutils libbcc libdl
+LOCAL_LDLIBS := -lpthread
+
+ifeq ($(TARGET_ARCH),arm)
+	LOCAL_CFLAGS += -fstrict-aliasing
+endif
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+    # we need to access the private Bionic header <bionic_tls.h>
+    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+    # behavior from the bionic Android.mk file
+    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+    endif
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+#replace libagl for now
+LOCAL_MODULE:= libGLES_android
+LOCAL_MODULE_TAGS := eng
+
+## Disable this makefile for now
+## include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libagl2/README b/opengl/libagl2/README
new file mode 100644
index 0000000..34746d3
--- /dev/null
+++ b/opengl/libagl2/README
@@ -0,0 +1,26 @@
+libAgl2 provides software GL ES 2.0 implementation using Pixelflinger2 in external/mesa3d
+
+To build, enable Android.mk, which builds libGLES_android.so, then replace the one built from libAgl in system/lib/egl.
+ES 1.0 functions are not implemented and will cause exit, so do not setprop debug.egl.hw 0 until launcher is loaded.
+
+All functions have little to none error checking.
+Not thread safe, Pixelflinger2 uses some static data.
+
+Most shader functions are implemented, however, most Get* functions for shaders/programs/uniforms/attribs are not.
+No name system for shaders/programs, just using the pointers as names.
+
+Basic glTexImage2D, glTexSubImage2D, glCopyImage2D and glCopySubImage2D are implemented, with a range of 8/16/24/32bpp formats.
+Cube map support is minimal. No mipmapping.
+TexParameter is mostly implemented, supports texcoord wrap modes, and only linear for both min and mag, or nearest for both min and mag filtering.
+Texture names are implemented, but bad.
+
+Frame buffer and render buffers are not implemented.
+
+Depth and stencil are implemented, but not tested.
+Blending seems to work.
+Colorbuffer supports RGBA_8888 and RGB_565.
+
+Vertex buffer objects are implemented.
+Some GL_TRIANGLES and GL_TRIANGLE_STRIPS modes for glDrawArrays and glDrawElements are implemented, but vertex order is probably wrong so culling is disabled.
+
+Basic apps should work, and some libhwui should work, except for frame buffer operations, which will cause exit.
diff --git a/opengl/libagl2/libagl2.project b/opengl/libagl2/libagl2.project
new file mode 100644
index 0000000..f234421
--- /dev/null
+++ b/opengl/libagl2/libagl2.project
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<CodeLite_Project Name="libagl2" InternalType="Console">
+  <Plugins>
+    <Plugin Name="qmake">
+      <![CDATA[00010001N0005Debug000000000000]]>
+    </Plugin>
+  </Plugins>
+  <Description/>
+  <Dependencies/>
+  <Dependencies Name="Release"/>
+  <VirtualDirectory Name="src">
+    <File Name="src/egl.cpp"/>
+    <File Name="src/api.cpp"/>
+    <File Name="src/gles2context.h"/>
+    <File Name="src/shader.cpp"/>
+    <File Name="src/vertex.cpp"/>
+    <File Name="src/state.cpp"/>
+    <File Name="src/texture.cpp"/>
+    <File Name="src/get.cpp"/>
+  </VirtualDirectory>
+  <VirtualDirectory Name="include"/>
+  <Settings Type="Executable">
+    <Configuration Name="Debug" CompilerType="gnu gcc" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
+      <Compiler Options="-g;-m32" Required="yes" PreCompiledHeader="">
+        <IncludePath Value="/usr/include/c++/4.4"/>
+        <IncludePath Value="/usr/include/c++/4.4/ext"/>
+        <IncludePath Value="."/>
+        <IncludePath Value="include"/>
+        <IncludePath Value="../../../../external/mesa3d/include"/>
+        <IncludePath Value="../../../../external/mesa3d/src"/>
+        <IncludePath Value="../../../../hardware/libhardware/include"/>
+        <IncludePath Value="../../../../system/core/include"/>
+        <IncludePath Value="../include"/>
+        <IncludePath Value="../../include"/>
+        <IncludePath Value="../../../../development/ndk/platforms/android-9/include"/>
+        <IncludePath Value="../../../../bionic/libc/include/"/>
+        <IncludePath Value="/../../../../development/ndk/platforms/android-5/arch-x86/include"/>
+        <IncludePath Value="../../../../bionic/libc/arch-x86/include"/>
+        <IncludePath Value="../../../../bionic/libc/kernel/arch-x86"/>
+        <IncludePath Value="/../../../../external/kernel-headers/original"/>
+        <IncludePath Value="../../../../prebuilt/ndk/android-ndk-r4/platforms/android-8/arch-x86/usr/include"/>
+      </Compiler>
+      <Linker Options="-m32;-lstdc++" Required="yes"/>
+      <ResourceCompiler Options="" Required="no"/>
+      <General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
+      <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
+        <PostConnectCommands/>
+        <StartupCommands/>
+      </Debugger>
+      <PreBuild/>
+      <PostBuild/>
+      <CustomBuild Enabled="no">
+        <RebuildCommand/>
+        <CleanCommand/>
+        <BuildCommand/>
+        <PreprocessFileCommand/>
+        <SingleFileCommand/>
+        <MakefileGenerationCommand/>
+        <ThirdPartyToolName>None</ThirdPartyToolName>
+        <WorkingDirectory/>
+      </CustomBuild>
+      <AdditionalRules>
+        <CustomPostBuild/>
+        <CustomPreBuild/>
+      </AdditionalRules>
+    </Configuration>
+    <Configuration Name="Release" CompilerType="gnu gcc" DebuggerType="GNU gdb debugger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
+      <Compiler Options="" Required="yes" PreCompiledHeader="">
+        <IncludePath Value="."/>
+      </Compiler>
+      <Linker Options="-O2" Required="yes"/>
+      <ResourceCompiler Options="" Required="no"/>
+      <General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Release" Command="./$(ProjectName)" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
+      <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
+        <PostConnectCommands/>
+        <StartupCommands/>
+      </Debugger>
+      <PreBuild/>
+      <PostBuild/>
+      <CustomBuild Enabled="no">
+        <RebuildCommand/>
+        <CleanCommand/>
+        <BuildCommand/>
+        <PreprocessFileCommand/>
+        <SingleFileCommand/>
+        <MakefileGenerationCommand/>
+        <ThirdPartyToolName>None</ThirdPartyToolName>
+        <WorkingDirectory/>
+      </CustomBuild>
+      <AdditionalRules>
+        <CustomPostBuild/>
+        <CustomPreBuild/>
+      </AdditionalRules>
+    </Configuration>
+    <GlobalSettings>
+      <Compiler Options="">
+        <IncludePath Value="."/>
+      </Compiler>
+      <Linker Options="">
+        <LibraryPath Value="."/>
+      </Linker>
+      <ResourceCompiler Options=""/>
+    </GlobalSettings>
+  </Settings>
+  <Dependencies Name="Debug">
+    <Project Name="libMesa"/>
+  </Dependencies>
+</CodeLite_Project>
diff --git a/opengl/libagl2/src/api.cpp b/opengl/libagl2/src/api.cpp
new file mode 100644
index 0000000..bb8d62b
--- /dev/null
+++ b/opengl/libagl2/src/api.cpp
@@ -0,0 +1,266 @@
+#include "gles2context.h"
+
+#define API_ENTRY
+#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0);
+#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0;
+
+
+void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer)
+{
+   CALL_GL_API(glBindFramebuffer, target, framebuffer);
+}
+void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer)
+{
+   CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
+}
+GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target)
+{
+   CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+   CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers)
+{
+   CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers)
+{
+   CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDepthFunc)(GLenum func)
+{
+   CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag)
+{
+   CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar)
+{
+   CALL_GL_API(glDepthRangef, zNear, zFar);
+}
+void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+   CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+   CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
+}
+void glGenerateMipmap(GLenum target)
+{
+   //CALL_GL_API(glGenerateMipmap, target);
+   LOGD("agl2: glGenerateMipmap not implemented");
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint* framebuffers)
+{
+   CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers)
+{
+   CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+   CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+   CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+   CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params)
+{
+   CALL_GL_API(glGetBooleanv, pname, params);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+GLenum glGetError(void)
+{
+   puts("agl2: glGetError");
+   return GL_NO_ERROR;
+   //CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params)
+{
+   CALL_GL_API(glGetFloatv, pname, params);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
+}
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+   CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
+}
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+   CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
+}
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params)
+{
+   CALL_GL_API(glGetUniformfv, program, location, params);
+}
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params)
+{
+   CALL_GL_API(glGetUniformiv, program, location, params);
+}
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params)
+{
+   CALL_GL_API(glGetVertexAttribfv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetVertexAttribiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer)
+{
+   CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
+}
+GLboolean API_ENTRY(glIsBuffer)(GLuint buffer)
+{
+   CALL_GL_API_RETURN(glIsBuffer, buffer);
+}
+GLboolean API_ENTRY(glIsEnabled)(GLenum cap)
+{
+   CALL_GL_API_RETURN(glIsEnabled, cap);
+}
+GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer)
+{
+   CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
+}
+GLboolean API_ENTRY(glIsProgram)(GLuint program)
+{
+   CALL_GL_API_RETURN(glIsProgram, program);
+}
+GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer)
+{
+   CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
+}
+GLboolean API_ENTRY(glIsShader)(GLuint shader)
+{
+   CALL_GL_API_RETURN(glIsShader, shader);
+}
+void API_ENTRY(glLineWidth)(GLfloat width)
+{
+   CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units)
+{
+   CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+   CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glReleaseShaderCompiler)(void)
+{
+   CALL_GL_API(glReleaseShaderCompiler);
+}
+void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+   CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert)
+{
+   CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+{
+   CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask)
+{
+   CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+   CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask)
+{
+   CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask)
+{
+   CALL_GL_API(glStencilMaskSeparate, face, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass)
+{
+   CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+   CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
+}
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform1fv, location, count, v);
+}
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform1iv, location, count, v);
+}
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform2fv, location, count, v);
+}
+void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y)
+{
+   CALL_GL_API(glUniform2i, location, x, y);
+}
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform2iv, location, count, v);
+}
+void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+   CALL_GL_API(glUniform3f, location, x, y, z);
+}
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform3fv, location, count, v);
+}
+void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z)
+{
+   CALL_GL_API(glUniform3i, location, x, y, z);
+}
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform3iv, location, count, v);
+}
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat* v)
+{
+   CALL_GL_API(glUniform4fv, location, count, v);
+}
+void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+   CALL_GL_API(glUniform4i, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint* v)
+{
+   CALL_GL_API(glUniform4iv, location, count, v);
+}
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+   CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+   CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
+}
+void API_ENTRY(glValidateProgram)(GLuint program)
+{
+   CALL_GL_API(glValidateProgram, program);
+}
diff --git a/opengl/libagl2/src/egl.cpp b/opengl/libagl2/src/egl.cpp
new file mode 100644
index 0000000..6184644
--- /dev/null
+++ b/opengl/libagl2/src/egl.cpp
@@ -0,0 +1,2232 @@
+/*
+**
+** 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 <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <cutils/atomic.h>
+
+
+#include <private/ui/android_natives_priv.h>
+
+#include <hardware/copybit.h>
+
+#include "gles2context.h"
+
+// ----------------------------------------------------------------------------
+namespace android
+{
+// ----------------------------------------------------------------------------
+
+const unsigned int NUM_DISPLAYS = 1;
+
+static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_key_t gEGLErrorKey = -1;
+#ifndef HAVE_ANDROID_OS
+namespace gl {
+pthread_key_t gGLKey = -1;
+}; // namespace gl
+#endif
+
+template<typename T>
+static T setError(GLint error, T returnValue)
+{
+   if (ggl_unlikely(gEGLErrorKey == -1)) {
+      pthread_mutex_lock(&gErrorKeyMutex);
+      if (gEGLErrorKey == -1)
+         pthread_key_create(&gEGLErrorKey, NULL);
+      pthread_mutex_unlock(&gErrorKeyMutex);
+   }
+   pthread_setspecific(gEGLErrorKey, (void*)error);
+   return returnValue;
+}
+
+static GLint getError()
+{
+   if (ggl_unlikely(gEGLErrorKey == -1))
+      return EGL_SUCCESS;
+   GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
+   if (error == 0) {
+      // The TLS key has been created by another thread, but the value for
+      // this thread has not been initialized.
+      return EGL_SUCCESS;
+   }
+   pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
+   return error;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_display_t {
+   egl_display_t() : type(0), initialized(0) { }
+
+   static egl_display_t& get_display(EGLDisplay dpy);
+
+   static EGLBoolean is_valid(EGLDisplay dpy) {
+      return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
+   }
+
+   NativeDisplayType   type;
+   volatile int32_t    initialized;
+};
+
+static egl_display_t gDisplays[NUM_DISPLAYS];
+
+egl_display_t& egl_display_t::get_display(EGLDisplay dpy)
+{
+   return gDisplays[uintptr_t(dpy)-1U];
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_surface_t {
+   enum {
+      PAGE_FLIP = 0x00000001,
+      MAGIC     = 0x31415265
+   };
+
+   uint32_t            magic;
+   EGLDisplay          dpy;
+   EGLConfig           config;
+   EGLContext          ctx;
+
+   egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
+   virtual     ~egl_surface_t();
+   bool    isValid() const;
+   virtual     bool    initCheck() const = 0;
+
+   virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl) = 0;
+   virtual     EGLBoolean  bindReadSurface(GLES2Context* gl) = 0;
+   virtual     EGLBoolean  connect() {
+      return EGL_TRUE;
+   }
+   virtual     void        disconnect() {}
+   virtual     EGLint      getWidth() const = 0;
+   virtual     EGLint      getHeight() const = 0;
+
+   virtual     EGLint      getHorizontalResolution() const;
+   virtual     EGLint      getVerticalResolution() const;
+   virtual     EGLint      getRefreshRate() const;
+   virtual     EGLint      getSwapBehavior() const;
+   virtual     EGLBoolean  swapBuffers();
+   virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+protected:
+   GGLSurface              depth;
+};
+
+egl_surface_t::egl_surface_t(EGLDisplay dpy,
+                             EGLConfig config,
+                             int32_t depthFormat)
+      : magic(MAGIC), dpy(dpy), config(config), ctx(0)
+{
+   depth.version = sizeof(GGLSurface);
+   depth.data = 0;
+   depth.format = (GGLPixelFormat)depthFormat;
+}
+egl_surface_t::~egl_surface_t()
+{
+   magic = 0;
+   free(depth.data);
+}
+bool egl_surface_t::isValid() const
+{
+   LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
+   return magic == MAGIC;
+}
+
+EGLBoolean egl_surface_t::swapBuffers()
+{
+   return EGL_FALSE;
+}
+EGLint egl_surface_t::getHorizontalResolution() const
+{
+   return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_surface_t::getVerticalResolution() const
+{
+   return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_surface_t::getRefreshRate() const
+{
+   return (60 * EGL_DISPLAY_SCALING);
+}
+EGLint egl_surface_t::getSwapBehavior() const
+{
+   return EGL_BUFFER_PRESERVED;
+}
+EGLBoolean egl_surface_t::setSwapRectangle(
+   EGLint l, EGLint t, EGLint w, EGLint h)
+{
+   return EGL_FALSE;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_window_surface_v2_t : public egl_surface_t {
+   egl_window_surface_v2_t(
+      EGLDisplay dpy, EGLConfig config,
+      int32_t depthFormat,
+      ANativeWindow* window);
+
+   ~egl_window_surface_v2_t();
+
+   virtual     bool        initCheck() const {
+      return true;   // TODO: report failure if ctor fails
+   }
+   virtual     EGLBoolean  swapBuffers();
+   virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl);
+   virtual     EGLBoolean  bindReadSurface(GLES2Context* gl);
+   virtual     EGLBoolean  connect();
+   virtual     void        disconnect();
+   virtual     EGLint      getWidth() const    {
+      return width;
+   }
+   virtual     EGLint      getHeight() const   {
+      return height;
+   }
+   virtual     EGLint      getHorizontalResolution() const;
+   virtual     EGLint      getVerticalResolution() const;
+   virtual     EGLint      getRefreshRate() const;
+   virtual     EGLint      getSwapBehavior() const;
+   virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+
+private:
+   status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
+   status_t unlock(android_native_buffer_t* buf);
+   ANativeWindow*   nativeWindow;
+   android_native_buffer_t*   buffer;
+   android_native_buffer_t*   previousBuffer;
+   gralloc_module_t const*    module;
+   copybit_device_t*          blitengine;
+   int width;
+   int height;
+   void* bits;
+   GGLFormat const* pixelFormatTable;
+
+   struct Rect {
+      inline Rect() { };
+      inline Rect(int32_t w, int32_t h)
+            : left(0), top(0), right(w), bottom(h) { }
+      inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
+            : left(l), top(t), right(r), bottom(b) { }
+      Rect& andSelf(const Rect& r) {
+         left   = max(left, r.left);
+         top    = max(top, r.top);
+         right  = min(right, r.right);
+         bottom = min(bottom, r.bottom);
+         return *this;
+      }
+      bool isEmpty() const {
+         return (left>=right || top>=bottom);
+      }
+      void dump(char const* what) {
+         LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
+              what, left, top, right-left, bottom-top);
+      }
+
+      int32_t left;
+      int32_t top;
+      int32_t right;
+      int32_t bottom;
+   };
+
+   struct Region {
+      inline Region() : count(0) { }
+      typedef Rect const* const_iterator;
+      const_iterator begin() const {
+         return storage;
+      }
+      const_iterator end() const {
+         return storage+count;
+      }
+      static Region subtract(const Rect& lhs, const Rect& rhs) {
+         Region reg;
+         Rect* storage = reg.storage;
+         if (!lhs.isEmpty()) {
+            if (lhs.top < rhs.top) { // top rect
+               storage->left   = lhs.left;
+               storage->top    = lhs.top;
+               storage->right  = lhs.right;
+               storage->bottom = rhs.top;
+               storage++;
+            }
+            const int32_t top = max(lhs.top, rhs.top);
+            const int32_t bot = min(lhs.bottom, rhs.bottom);
+            if (top < bot) {
+               if (lhs.left < rhs.left) { // left-side rect
+                  storage->left   = lhs.left;
+                  storage->top    = top;
+                  storage->right  = rhs.left;
+                  storage->bottom = bot;
+                  storage++;
+               }
+               if (lhs.right > rhs.right) { // right-side rect
+                  storage->left   = rhs.right;
+                  storage->top    = top;
+                  storage->right  = lhs.right;
+                  storage->bottom = bot;
+                  storage++;
+               }
+            }
+            if (lhs.bottom > rhs.bottom) { // bottom rect
+               storage->left   = lhs.left;
+               storage->top    = rhs.bottom;
+               storage->right  = lhs.right;
+               storage->bottom = lhs.bottom;
+               storage++;
+            }
+            reg.count = storage - reg.storage;
+         }
+         return reg;
+      }
+      bool isEmpty() const {
+         return count<=0;
+      }
+private:
+      Rect storage[4];
+      ssize_t count;
+   };
+
+   struct region_iterator : public copybit_region_t {
+      region_iterator(const Region& region)
+            : b(region.begin()), e(region.end()) {
+         this->next = iterate;
+      }
+private:
+      static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+         region_iterator const* me = static_cast<region_iterator const*>(self);
+         if (me->b != me->e) {
+            *reinterpret_cast<Rect*>(rect) = *me->b++;
+            return 1;
+         }
+         return 0;
+      }
+      mutable Region::const_iterator b;
+      Region::const_iterator const e;
+   };
+
+   void copyBlt(
+      android_native_buffer_t* dst, void* dst_vaddr,
+      android_native_buffer_t* src, void const* src_vaddr,
+      const Region& clip);
+
+   Rect dirtyRegion;
+   Rect oldDirtyRegion;
+};
+
+egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
+      EGLConfig config,
+      int32_t depthFormat,
+      ANativeWindow* window)
+      : egl_surface_t(dpy, config, depthFormat),
+      nativeWindow(window), buffer(0), previousBuffer(0), module(0),
+      blitengine(0), bits(NULL)
+{
+   hw_module_t const* pModule;
+   hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
+   module = reinterpret_cast<gralloc_module_t const*>(pModule);
+
+   if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) {
+      copybit_open(pModule, &blitengine);
+   }
+
+   pixelFormatTable = gglGetPixelFormatTable();
+
+   // keep a reference on the window
+   nativeWindow->common.incRef(&nativeWindow->common);
+   nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
+   nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
+   int format = 0;
+   nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format);
+   LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format);
+//   assert(0);
+}
+
+egl_window_surface_v2_t::~egl_window_surface_v2_t()
+{
+   if (buffer) {
+      buffer->common.decRef(&buffer->common);
+   }
+   if (previousBuffer) {
+      previousBuffer->common.decRef(&previousBuffer->common);
+   }
+   nativeWindow->common.decRef(&nativeWindow->common);
+   if (blitengine) {
+      copybit_close(blitengine);
+   }
+}
+
+EGLBoolean egl_window_surface_v2_t::connect()
+{
+   // we're intending to do software rendering
+   native_window_set_usage(nativeWindow,
+                           GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+   // dequeue a buffer
+   if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
+      return setError(EGL_BAD_ALLOC, EGL_FALSE);
+   }
+
+   // allocate a corresponding depth-buffer
+   width = buffer->width;
+   height = buffer->height;
+   if (depth.format) {
+      depth.width   = width;
+      depth.height  = height;
+      depth.stride  = depth.width; // use the width here
+      assert(GGL_PIXEL_FORMAT_Z_32 == depth.format);
+      depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*4);
+      if (depth.data == 0) {
+         return setError(EGL_BAD_ALLOC, EGL_FALSE);
+      }
+   }
+
+   // keep a reference on the buffer
+   buffer->common.incRef(&buffer->common);
+
+   // Lock the buffer
+   nativeWindow->lockBuffer(nativeWindow, buffer);
+   // pin the buffer down
+   if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+            GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+      LOGE("connect() failed to lock buffer %p (%ux%u)",
+           buffer, buffer->width, buffer->height);
+      return setError(EGL_BAD_ACCESS, EGL_FALSE);
+      // FIXME: we should make sure we're not accessing the buffer anymore
+   }
+   return EGL_TRUE;
+}
+
+void egl_window_surface_v2_t::disconnect()
+{
+   if (buffer && bits) {
+      bits = NULL;
+      unlock(buffer);
+   }
+   // enqueue the last frame
+   if (buffer)
+      nativeWindow->queueBuffer(nativeWindow, buffer);
+   if (buffer) {
+      buffer->common.decRef(&buffer->common);
+      buffer = 0;
+   }
+   if (previousBuffer) {
+      previousBuffer->common.decRef(&previousBuffer->common);
+      previousBuffer = 0;
+   }
+}
+
+status_t egl_window_surface_v2_t::lock(
+   android_native_buffer_t* buf, int usage, void** vaddr)
+{
+   int err;
+
+   err = module->lock(module, buf->handle,
+                      usage, 0, 0, buf->width, buf->height, vaddr);
+
+   return err;
+}
+
+status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
+{
+   if (!buf) return BAD_VALUE;
+   int err = NO_ERROR;
+
+   err = module->unlock(module, buf->handle);
+
+   return err;
+}
+
+void egl_window_surface_v2_t::copyBlt(
+   android_native_buffer_t* dst, void* dst_vaddr,
+   android_native_buffer_t* src, void const* src_vaddr,
+   const Region& clip)
+{
+   // FIXME: use copybit if possible
+   // NOTE: dst and src must be the same format
+
+   status_t err = NO_ERROR;
+   copybit_device_t* const copybit = blitengine;
+   if (copybit)  {
+      copybit_image_t simg;
+      simg.w = src->stride;
+      simg.h = src->height;
+      simg.format = src->format;
+      simg.handle = const_cast<native_handle_t*>(src->handle);
+
+      copybit_image_t dimg;
+      dimg.w = dst->stride;
+      dimg.h = dst->height;
+      dimg.format = dst->format;
+      dimg.handle = const_cast<native_handle_t*>(dst->handle);
+
+      copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+      copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
+      copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+      region_iterator it(clip);
+      err = copybit->blit(copybit, &dimg, &simg, &it);
+      if (err != NO_ERROR) {
+         LOGE("copybit failed (%s)", strerror(err));
+      }
+   }
+
+   if (!copybit || err) {
+      Region::const_iterator cur = clip.begin();
+      Region::const_iterator end = clip.end();
+
+      const size_t bpp = pixelFormatTable[src->format].size;
+      const size_t dbpr = dst->stride * bpp;
+      const size_t sbpr = src->stride * bpp;
+
+      uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+      uint8_t       * const dst_bits = (uint8_t       *)dst_vaddr;
+
+      while (cur != end) {
+         const Rect& r(*cur++);
+         ssize_t w = r.right - r.left;
+         ssize_t h = r.bottom - r.top;
+         if (w <= 0 || h<=0) continue;
+         size_t size = w * bpp;
+         uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+         uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+         if (dbpr==sbpr && size==sbpr) {
+            size *= h;
+            h = 1;
+         }
+         do {
+            memcpy(d, s, size);
+            d += dbpr;
+            s += sbpr;
+         } while (--h > 0);
+      }
+   }
+}
+
+EGLBoolean egl_window_surface_v2_t::swapBuffers()
+{
+   if (!buffer) {
+      return setError(EGL_BAD_ACCESS, EGL_FALSE);
+   }
+
+   /*
+    * Handle eglSetSwapRectangleANDROID()
+    * We copyback from the front buffer
+    */
+   if (!dirtyRegion.isEmpty()) {
+      dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
+      if (previousBuffer) {
+         // This was const Region copyBack, but that causes an
+         // internal compile error on simulator builds
+         /*const*/
+         Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+         if (!copyBack.isEmpty()) {
+            void* prevBits;
+            if (lock(previousBuffer,
+                     GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
+               // copy from previousBuffer to buffer
+               copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
+               unlock(previousBuffer);
+            }
+         }
+      }
+      oldDirtyRegion = dirtyRegion;
+   }
+
+   if (previousBuffer) {
+      previousBuffer->common.decRef(&previousBuffer->common);
+      previousBuffer = 0;
+   }
+
+   unlock(buffer);
+   previousBuffer = buffer;
+   nativeWindow->queueBuffer(nativeWindow, buffer);
+   buffer = 0;
+
+   // dequeue a new buffer
+   if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
+
+      // TODO: lockBuffer should rather be executed when the very first
+      // direct rendering occurs.
+      nativeWindow->lockBuffer(nativeWindow, buffer);
+
+      // reallocate the depth-buffer if needed
+      if ((width != buffer->width) || (height != buffer->height)) {
+         // TODO: we probably should reset the swap rect here
+         // if the window size has changed
+         width = buffer->width;
+         height = buffer->height;
+         if (depth.data) {
+            free(depth.data);
+            depth.width   = width;
+            depth.height  = height;
+            depth.stride  = buffer->stride;
+            depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
+            if (depth.data == 0) {
+               setError(EGL_BAD_ALLOC, EGL_FALSE);
+               return EGL_FALSE;
+            }
+         }
+      }
+
+      // keep a reference on the buffer
+      buffer->common.incRef(&buffer->common);
+
+      // finally pin the buffer down
+      if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+               GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+         LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+              buffer, buffer->width, buffer->height);
+         return setError(EGL_BAD_ACCESS, EGL_FALSE);
+         // FIXME: we should make sure we're not accessing the buffer anymore
+      }
+   } else {
+      return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
+   }
+
+   return EGL_TRUE;
+}
+
+EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
+   EGLint l, EGLint t, EGLint w, EGLint h)
+{
+   dirtyRegion = Rect(l, t, l+w, t+h);
+   return EGL_TRUE;
+}
+
+EGLBoolean egl_window_surface_v2_t::bindDrawSurface(GLES2Context* gl)
+{
+   GGLSurface buffer;
+   buffer.version = sizeof(GGLSurface);
+   buffer.width   = this->buffer->width;
+   buffer.height  = this->buffer->height;
+   buffer.stride  = this->buffer->stride;
+   buffer.data    = (GGLubyte*)bits;
+   buffer.format  = (GGLPixelFormat)this->buffer->format;
+   gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
+   if (depth.data != gl->rasterizer.depthSurface.data)
+      gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+
+   return EGL_TRUE;
+}
+EGLBoolean egl_window_surface_v2_t::bindReadSurface(GLES2Context* gl)
+{
+   GGLSurface buffer;
+   buffer.version = sizeof(GGLSurface);
+   buffer.width   = this->buffer->width;
+   buffer.height  = this->buffer->height;
+   buffer.stride  = this->buffer->stride;
+   buffer.data    = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
+   buffer.format  = (GGLPixelFormat)this->buffer->format;
+   puts("agl2: readBuffer not implemented");
+   //gl->rasterizer.interface.readBuffer(gl, &buffer);
+   return EGL_TRUE;
+}
+EGLint egl_window_surface_v2_t::getHorizontalResolution() const
+{
+   return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_window_surface_v2_t::getVerticalResolution() const
+{
+   return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+}
+EGLint egl_window_surface_v2_t::getRefreshRate() const
+{
+   return (60 * EGL_DISPLAY_SCALING); // FIXME
+}
+EGLint egl_window_surface_v2_t::getSwapBehavior() const
+{
+   /*
+    * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
+    * the content of the swapped buffer.
+    *
+    * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
+    *
+    * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
+    * only applies to the area specified by eglSetSwapRectangleANDROID(), that
+    * is, everything outside of this area is preserved.
+    *
+    * This implementation of EGL assumes the later case.
+    *
+    */
+
+   return EGL_BUFFER_DESTROYED;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_pixmap_surface_t : public egl_surface_t {
+   egl_pixmap_surface_t(
+      EGLDisplay dpy, EGLConfig config,
+      int32_t depthFormat,
+      egl_native_pixmap_t const * pixmap);
+
+   virtual ~egl_pixmap_surface_t() { }
+
+   virtual     bool        initCheck() const {
+      return !depth.format || depth.data!=0;
+   }
+   virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl);
+   virtual     EGLBoolean  bindReadSurface(GLES2Context* gl);
+   virtual     EGLint      getWidth() const    {
+      return nativePixmap.width;
+   }
+   virtual     EGLint      getHeight() const   {
+      return nativePixmap.height;
+   }
+private:
+   egl_native_pixmap_t     nativePixmap;
+};
+
+egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
+      EGLConfig config,
+      int32_t depthFormat,
+      egl_native_pixmap_t const * pixmap)
+      : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
+{
+   if (depthFormat) {
+      depth.width   = pixmap->width;
+      depth.height  = pixmap->height;
+      depth.stride  = depth.width; // use the width here
+      depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
+      if (depth.data == 0) {
+         setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+      }
+   }
+}
+EGLBoolean egl_pixmap_surface_t::bindDrawSurface(GLES2Context* gl)
+{
+   GGLSurface buffer;
+   buffer.version = sizeof(GGLSurface);
+   buffer.width   = nativePixmap.width;
+   buffer.height  = nativePixmap.height;
+   buffer.stride  = nativePixmap.stride;
+   buffer.data    = nativePixmap.data;
+   buffer.format  = (GGLPixelFormat)nativePixmap.format;
+
+   gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
+   if (depth.data != gl->rasterizer.depthSurface.data)
+      gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+   return EGL_TRUE;
+}
+EGLBoolean egl_pixmap_surface_t::bindReadSurface(GLES2Context* gl)
+{
+   GGLSurface buffer;
+   buffer.version = sizeof(GGLSurface);
+   buffer.width   = nativePixmap.width;
+   buffer.height  = nativePixmap.height;
+   buffer.stride  = nativePixmap.stride;
+   buffer.data    = nativePixmap.data;
+   buffer.format  = (GGLPixelFormat)nativePixmap.format;
+   puts("agl2: readBuffer not implemented");
+   //gl->rasterizer.interface.readBuffer(gl, &buffer);
+   return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+
+struct egl_pbuffer_surface_t : public egl_surface_t {
+   egl_pbuffer_surface_t(
+      EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
+      int32_t w, int32_t h, int32_t f);
+
+   virtual ~egl_pbuffer_surface_t();
+
+   virtual     bool        initCheck() const   {
+      return pbuffer.data != 0;
+   }
+   virtual     EGLBoolean  bindDrawSurface(GLES2Context* gl);
+   virtual     EGLBoolean  bindReadSurface(GLES2Context* gl);
+   virtual     EGLint      getWidth() const    {
+      return pbuffer.width;
+   }
+   virtual     EGLint      getHeight() const   {
+      return pbuffer.height;
+   }
+private:
+   GGLSurface  pbuffer;
+};
+
+egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
+      EGLConfig config, int32_t depthFormat,
+      int32_t w, int32_t h, int32_t f)
+      : egl_surface_t(dpy, config, depthFormat)
+{
+   size_t size = w*h;
+   switch (f) {
+   case GGL_PIXEL_FORMAT_A_8:
+      size *= 1;
+      break;
+   case GGL_PIXEL_FORMAT_RGB_565:
+      size *= 2;
+      break;
+   case GGL_PIXEL_FORMAT_RGBA_8888:
+      size *= 4;
+      break;
+   case GGL_PIXEL_FORMAT_RGBX_8888:
+      size *= 4;
+      break;
+   default:
+      LOGE("incompatible pixel format for pbuffer (format=%d)", f);
+      pbuffer.data = 0;
+      break;
+   }
+   pbuffer.version = sizeof(GGLSurface);
+   pbuffer.width   = w;
+   pbuffer.height  = h;
+   pbuffer.stride  = w;
+   pbuffer.data    = (GGLubyte*)malloc(size);
+   pbuffer.format  = (GGLPixelFormat)f;
+
+   if (depthFormat) {
+      depth.width   = pbuffer.width;
+      depth.height  = pbuffer.height;
+      depth.stride  = depth.width; // use the width here
+      depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
+      if (depth.data == 0) {
+         setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+         return;
+      }
+   }
+}
+egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
+{
+   free(pbuffer.data);
+}
+EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(GLES2Context* gl)
+{
+   gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer);
+   if (depth.data != gl->rasterizer.depthSurface.data)
+      gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+   return EGL_TRUE;
+}
+EGLBoolean egl_pbuffer_surface_t::bindReadSurface(GLES2Context* gl)
+{
+   puts("agl2: readBuffer not implemented");
+   //gl->rasterizer.interface.readBuffer(gl, &pbuffer);
+   return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+
+struct config_pair_t {
+   GLint key;
+   GLint value;
+};
+
+struct configs_t {
+   const config_pair_t* array;
+   int                  size;
+};
+
+struct config_management_t {
+   GLint key;
+   bool (*match)(GLint reqValue, GLint confValue);
+   static bool atLeast(GLint reqValue, GLint confValue) {
+      return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
+   }
+   static bool exact(GLint reqValue, GLint confValue) {
+      return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
+   }
+   static bool mask(GLint reqValue, GLint confValue) {
+      return (confValue & reqValue) == reqValue;
+   }
+   static bool ignore(GLint reqValue, GLint confValue) {
+      return true;
+   }
+};
+
+// ----------------------------------------------------------------------------
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 2
+static char const * const gVendorString     = "Google Inc.";
+static char const * const gVersionString    = "0.0 Android Driver 0.0.0";
+static char const * const gClientApiString  = "OpenGL ES2";
+static char const * const gExtensionsString =
+   //"EGL_KHR_image_base "
+   // "KHR_image_pixmap "
+   //"EGL_ANDROID_image_native_buffer "
+   //"EGL_ANDROID_swap_rectangle "
+   "";
+
+// ----------------------------------------------------------------------------
+
+struct extention_map_t {
+   const char * const name;
+   __eglMustCastToProperFunctionPointerType address;
+};
+
+static const extention_map_t gExtentionMap[] = {
+//    { "glDrawTexsOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
+//    { "glDrawTexiOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
+//    { "glDrawTexfOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
+//    { "glDrawTexxOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
+//    { "glDrawTexsvOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
+//    { "glDrawTexivOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
+//    { "glDrawTexfvOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
+//    { "glDrawTexxvOES",
+//            (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
+//    { "glQueryMatrixxOES",
+//            (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+//    { "glEGLImageTargetTexture2DOES",
+//            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
+//    { "glEGLImageTargetRenderbufferStorageOES",
+//            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
+//    { "glClipPlanef",
+//            (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
+//    { "glClipPlanex",
+//            (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
+//    { "glBindBuffer",
+//            (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
+//    { "glBufferData",
+//            (__eglMustCastToProperFunctionPointerType)&glBufferData },
+//    { "glBufferSubData",
+//            (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
+//    { "glDeleteBuffers",
+//            (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
+//    { "glGenBuffers",
+//            (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
+//    { "eglCreateImageKHR",
+//            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
+//    { "eglDestroyImageKHR",
+//            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
+//    { "eglSetSwapRectangleANDROID",
+//            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
+};
+
+/*
+ * In the lists below, attributes names MUST be sorted.
+ * Additionally, all configs must be sorted according to
+ * the EGL specification.
+ */
+
+static config_pair_t const config_base_attribute_list[] = {
+   { EGL_STENCIL_SIZE,               0                                 },
+   { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
+   { EGL_LEVEL,                      0                                 },
+   { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
+   { EGL_MAX_PBUFFER_PIXELS,
+     GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
+   { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
+   { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
+   { EGL_NATIVE_VISUAL_ID,           0                                 },
+   { EGL_NATIVE_VISUAL_TYPE,         GGL_PIXEL_FORMAT_RGBA_8888        },
+   { EGL_SAMPLES,                    0                                 },
+   { EGL_SAMPLE_BUFFERS,             0                                 },
+   { EGL_TRANSPARENT_TYPE,           EGL_NONE                          },
+   { EGL_TRANSPARENT_BLUE_VALUE,     0                                 },
+   { EGL_TRANSPARENT_GREEN_VALUE,    0                                 },
+   { EGL_TRANSPARENT_RED_VALUE,      0                                 },
+   { EGL_BIND_TO_TEXTURE_RGBA,       EGL_FALSE                         },
+   { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
+   { EGL_MIN_SWAP_INTERVAL,          1                                 },
+   { EGL_MAX_SWAP_INTERVAL,          1                                 },
+   { EGL_LUMINANCE_SIZE,             0                                 },
+   { EGL_ALPHA_MASK_SIZE,            0                                 },
+   { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
+   { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES2_BIT                },
+   { EGL_CONFORMANT,                 0                                 }
+};
+
+// These configs can override the base attribute list
+// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
+
+// 565 configs
+static config_pair_t const config_0_attribute_list[] = {
+   { EGL_BUFFER_SIZE,     16 },
+   { EGL_ALPHA_SIZE,       0 },
+   { EGL_BLUE_SIZE,        5 },
+   { EGL_GREEN_SIZE,       6 },
+   { EGL_RED_SIZE,         5 },
+   { EGL_DEPTH_SIZE,       0 },
+   { EGL_CONFIG_ID,        0 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_1_attribute_list[] = {
+   { EGL_BUFFER_SIZE,     16 },
+   { EGL_ALPHA_SIZE,       0 },
+   { EGL_BLUE_SIZE,        5 },
+   { EGL_GREEN_SIZE,       6 },
+   { EGL_RED_SIZE,         5 },
+   { EGL_DEPTH_SIZE,      16 },
+   { EGL_CONFIG_ID,        1 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// RGB 888 configs
+static config_pair_t const config_2_attribute_list[] = {
+   { EGL_BUFFER_SIZE,     32 },
+   { EGL_ALPHA_SIZE,       0 },
+   { EGL_BLUE_SIZE,        8 },
+   { EGL_GREEN_SIZE,       8 },
+   { EGL_RED_SIZE,         8 },
+   { EGL_DEPTH_SIZE,       0 },
+   { EGL_CONFIG_ID,        6 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_3_attribute_list[] = {
+   { EGL_BUFFER_SIZE,     32 },
+   { EGL_ALPHA_SIZE,       0 },
+   { EGL_BLUE_SIZE,        8 },
+   { EGL_GREEN_SIZE,       8 },
+   { EGL_RED_SIZE,         8 },
+   { EGL_DEPTH_SIZE,      16 },
+   { EGL_CONFIG_ID,        7 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// 8888 configs
+static config_pair_t const config_4_attribute_list[] = {
+   { EGL_BUFFER_SIZE,     32 },
+   { EGL_ALPHA_SIZE,       8 },
+   { EGL_BLUE_SIZE,        8 },
+   { EGL_GREEN_SIZE,       8 },
+   { EGL_RED_SIZE,         8 },
+   { EGL_DEPTH_SIZE,       0 },
+   { EGL_CONFIG_ID,        2 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_5_attribute_list[] = {
+   { EGL_BUFFER_SIZE,     32 },
+   { EGL_ALPHA_SIZE,       8 },
+   { EGL_BLUE_SIZE,        8 },
+   { EGL_GREEN_SIZE,       8 },
+   { EGL_RED_SIZE,         8 },
+   { EGL_DEPTH_SIZE,      16 },
+   { EGL_CONFIG_ID,        3 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// A8 configs
+static config_pair_t const config_6_attribute_list[] = {
+   { EGL_BUFFER_SIZE,      8 },
+   { EGL_ALPHA_SIZE,       8 },
+   { EGL_BLUE_SIZE,        0 },
+   { EGL_GREEN_SIZE,       0 },
+   { EGL_RED_SIZE,         0 },
+   { EGL_DEPTH_SIZE,       0 },
+   { EGL_CONFIG_ID,        4 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_7_attribute_list[] = {
+   { EGL_BUFFER_SIZE,      8 },
+   { EGL_ALPHA_SIZE,       8 },
+   { EGL_BLUE_SIZE,        0 },
+   { EGL_GREEN_SIZE,       0 },
+   { EGL_RED_SIZE,         0 },
+   { EGL_DEPTH_SIZE,      16 },
+   { EGL_CONFIG_ID,        5 },
+   { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
+   { EGL_SURFACE_TYPE,     EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static configs_t const gConfigs[] = {
+   { config_0_attribute_list, NELEM(config_0_attribute_list) },
+   { config_1_attribute_list, NELEM(config_1_attribute_list) },
+   { config_2_attribute_list, NELEM(config_2_attribute_list) },
+   { config_3_attribute_list, NELEM(config_3_attribute_list) },
+   { config_4_attribute_list, NELEM(config_4_attribute_list) },
+   { config_5_attribute_list, NELEM(config_5_attribute_list) },
+//   { config_6_attribute_list, NELEM(config_6_attribute_list) },
+//   { config_7_attribute_list, NELEM(config_7_attribute_list) },
+};
+
+static config_management_t const gConfigManagement[] = {
+   { EGL_BUFFER_SIZE,                config_management_t::atLeast },
+   { EGL_ALPHA_SIZE,                 config_management_t::atLeast },
+   { EGL_BLUE_SIZE,                  config_management_t::atLeast },
+   { EGL_GREEN_SIZE,                 config_management_t::atLeast },
+   { EGL_RED_SIZE,                   config_management_t::atLeast },
+   { EGL_DEPTH_SIZE,                 config_management_t::atLeast },
+   { EGL_STENCIL_SIZE,               config_management_t::atLeast },
+   { EGL_CONFIG_CAVEAT,              config_management_t::exact   },
+   { EGL_CONFIG_ID,                  config_management_t::exact   },
+   { EGL_LEVEL,                      config_management_t::exact   },
+   { EGL_MAX_PBUFFER_HEIGHT,         config_management_t::ignore   },
+   { EGL_MAX_PBUFFER_PIXELS,         config_management_t::ignore   },
+   { EGL_MAX_PBUFFER_WIDTH,          config_management_t::ignore   },
+   { EGL_NATIVE_RENDERABLE,          config_management_t::exact   },
+   { EGL_NATIVE_VISUAL_ID,           config_management_t::ignore   },
+   { EGL_NATIVE_VISUAL_TYPE,         config_management_t::exact   },
+   { EGL_SAMPLES,                    config_management_t::exact   },
+   { EGL_SAMPLE_BUFFERS,             config_management_t::exact   },
+   { EGL_SURFACE_TYPE,               config_management_t::mask    },
+   { EGL_TRANSPARENT_TYPE,           config_management_t::exact   },
+   { EGL_TRANSPARENT_BLUE_VALUE,     config_management_t::exact   },
+   { EGL_TRANSPARENT_GREEN_VALUE,    config_management_t::exact   },
+   { EGL_TRANSPARENT_RED_VALUE,      config_management_t::exact   },
+   { EGL_BIND_TO_TEXTURE_RGBA,       config_management_t::exact   },
+   { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
+   { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
+   { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
+   { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
+   { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
+   { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
+   { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
+   { EGL_CONFORMANT,                 config_management_t::mask    }
+};
+
+
+static config_pair_t const config_defaults[] = {
+   // attributes that are not specified are simply ignored, if a particular
+   // one needs not be ignored, it must be specified here, eg:
+   // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
+};
+
+// ----------------------------------------------------------------------------
+
+static status_t getConfigFormatInfo(EGLint configID,
+                                    int32_t& pixelFormat, int32_t& depthFormat)
+{
+   switch (configID) {
+   case 0:
+      pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+      depthFormat = 0;
+      break;
+   case 1:
+      pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+      depthFormat = GGL_PIXEL_FORMAT_Z_32;
+      break;
+   case 2:
+      pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+      depthFormat = 0;
+      break;
+   case 3:
+      pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+      depthFormat = GGL_PIXEL_FORMAT_Z_32;
+      break;
+   case 4:
+      pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+      depthFormat = 0;
+      break;
+   case 5:
+      pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+      depthFormat = GGL_PIXEL_FORMAT_Z_32;
+      break;
+   case 6:
+      pixelFormat = GGL_PIXEL_FORMAT_A_8;
+      depthFormat = 0;
+      break;
+   case 7:
+      pixelFormat = GGL_PIXEL_FORMAT_A_8;
+      depthFormat = GGL_PIXEL_FORMAT_Z_32;
+      break;
+   default:
+      return NAME_NOT_FOUND;
+   }
+   return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+template<typename T>
+static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
+{
+   while (first <= last) {
+      int mid = (first + last) / 2;
+      if (key > sortedArray[mid].key) {
+         first = mid + 1;
+      } else if (key < sortedArray[mid].key) {
+         last = mid - 1;
+      } else {
+         return mid;
+      }
+   }
+   return -1;
+}
+
+static int isAttributeMatching(int i, EGLint attr, EGLint val)
+{
+   // look for the attribute in all of our configs
+   config_pair_t const* configFound = gConfigs[i].array;
+   int index = binarySearch<config_pair_t>(
+                  gConfigs[i].array,
+                  0, gConfigs[i].size-1,
+                  attr);
+   if (index < 0) {
+      configFound = config_base_attribute_list;
+      index = binarySearch<config_pair_t>(
+                 config_base_attribute_list,
+                 0, NELEM(config_base_attribute_list)-1,
+                 attr);
+   }
+   if (index >= 0) {
+      // attribute found, check if this config could match
+      int cfgMgtIndex = binarySearch<config_management_t>(
+                           gConfigManagement,
+                           0, NELEM(gConfigManagement)-1,
+                           attr);
+      if (cfgMgtIndex >= 0) {
+         bool match = gConfigManagement[cfgMgtIndex].match(
+                         val, configFound[index].value);
+         if (match) {
+            // this config matches
+            return 1;
+         }
+      } else {
+         // attribute not found. this should NEVER happen.
+      }
+   } else {
+      // error, this attribute doesn't exist
+   }
+   return 0;
+}
+
+static int makeCurrent(GLES2Context* gl)
+{
+   GLES2Context* current = (GLES2Context*)getGlThreadSpecific();
+   if (gl) {
+      egl_context_t* c = egl_context_t::context(gl);
+      if (c->flags & egl_context_t::IS_CURRENT) {
+         if (current != gl) {
+            // it is an error to set a context current, if it's already
+            // current to another thread
+            return -1;
+         }
+      } else {
+         if (current) {
+            // mark the current context as not current, and flush
+            glFlush();
+            egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
+         }
+      }
+      if (!(c->flags & egl_context_t::IS_CURRENT)) {
+         // The context is not current, make it current!
+         setGlThreadSpecific(gl);
+         c->flags |= egl_context_t::IS_CURRENT;
+      }
+   } else {
+      if (current) {
+         // mark the current context as not current, and flush
+         glFlush();
+         egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
+      }
+      // this thread has no context attached to it
+      setGlThreadSpecific(0);
+   }
+   return 0;
+}
+
+static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
+                                  EGLint attribute, EGLint *value)
+{
+   size_t numConfigs =  NELEM(gConfigs);
+   int index = (int)config;
+   if (uint32_t(index) >= numConfigs)
+      return setError(EGL_BAD_CONFIG, EGL_FALSE);
+
+   int attrIndex;
+   attrIndex = binarySearch<config_pair_t>(
+                  gConfigs[index].array,
+                  0, gConfigs[index].size-1,
+                  attribute);
+   if (attrIndex>=0) {
+      *value = gConfigs[index].array[attrIndex].value;
+      return EGL_TRUE;
+   }
+
+   attrIndex = binarySearch<config_pair_t>(
+                  config_base_attribute_list,
+                  0, NELEM(config_base_attribute_list)-1,
+                  attribute);
+   if (attrIndex>=0) {
+      *value = config_base_attribute_list[attrIndex].value;
+      return EGL_TRUE;
+   }
+   return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+}
+
+static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
+                                      NativeWindowType window, const EGLint *attrib_list)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+   if (window == 0)
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   EGLint surfaceType;
+   if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+      return EGL_FALSE;
+
+   if (!(surfaceType & EGL_WINDOW_BIT))
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   if (reinterpret_cast<ANativeWindow*>(window)->common.magic !=
+         ANDROID_NATIVE_WINDOW_MAGIC) {
+      return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+   }
+
+   EGLint configID;
+   if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+      return EGL_FALSE;
+
+   int32_t depthFormat;
+   int32_t pixelFormat;
+   if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+   }
+
+   // FIXME: we don't have access to the pixelFormat here just yet.
+   // (it's possible that the surface is not fully initialized)
+   // maybe this should be done after the page-flip
+   //if (EGLint(info.format) != pixelFormat)
+   //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   egl_surface_t* surface;
+   surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
+                                         reinterpret_cast<ANativeWindow*>(window));
+
+   if (!surface->initCheck()) {
+      // there was a problem in the ctor, the error
+      // flag has been set.
+      delete surface;
+      surface = 0;
+   }
+   return surface;
+}
+
+static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
+                                      NativePixmapType pixmap, const EGLint *attrib_list)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+   if (pixmap == 0)
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   EGLint surfaceType;
+   if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+      return EGL_FALSE;
+
+   if (!(surfaceType & EGL_PIXMAP_BIT))
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version !=
+         sizeof(egl_native_pixmap_t)) {
+      return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+   }
+
+   EGLint configID;
+   if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+      return EGL_FALSE;
+
+   int32_t depthFormat;
+   int32_t pixelFormat;
+   if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+   }
+
+   if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat)
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   egl_surface_t* surface =
+      new egl_pixmap_surface_t(dpy, config, depthFormat,
+                               reinterpret_cast<egl_native_pixmap_t*>(pixmap));
+
+   if (!surface->initCheck()) {
+      // there was a problem in the ctor, the error
+      // flag has been set.
+      delete surface;
+      surface = 0;
+   }
+   return surface;
+}
+
+static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
+                                       const EGLint *attrib_list)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+
+   EGLint surfaceType;
+   if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+      return EGL_FALSE;
+
+   if (!(surfaceType & EGL_PBUFFER_BIT))
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+   EGLint configID;
+   if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+      return EGL_FALSE;
+
+   int32_t depthFormat;
+   int32_t pixelFormat;
+   if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+      return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+   }
+
+   int32_t w = 0;
+   int32_t h = 0;
+   while (attrib_list[0]) {
+      if (attrib_list[0] == EGL_WIDTH)  w = attrib_list[1];
+      if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
+      attrib_list+=2;
+   }
+
+   egl_surface_t* surface =
+      new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
+
+   if (!surface->initCheck()) {
+      // there was a problem in the ctor, the error
+      // flag has been set.
+      delete surface;
+      surface = 0;
+   }
+   return surface;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+// Initialization
+// ----------------------------------------------------------------------------
+
+EGLDisplay eglGetDisplay(NativeDisplayType display)
+{
+   puts("agl2:eglGetDisplay");
+#ifndef HAVE_ANDROID_OS
+   // this just needs to be done once
+   if (gGLKey == -1) {
+      pthread_mutex_lock(&gInitMutex);
+      if (gGLKey == -1)
+         pthread_key_create(&gGLKey, NULL);
+      pthread_mutex_unlock(&gInitMutex);
+   }
+#endif
+   if (display == EGL_DEFAULT_DISPLAY) {
+      EGLDisplay dpy = (EGLDisplay)1;
+      egl_display_t& d = egl_display_t::get_display(dpy);
+      d.type = display;
+      return dpy;
+   }
+   return EGL_NO_DISPLAY;
+}
+
+EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+   puts("agl2:eglInitialize");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   EGLBoolean res = EGL_TRUE;
+   egl_display_t& d = egl_display_t::get_display(dpy);
+
+   if (android_atomic_inc(&d.initialized) == 0) {
+      // initialize stuff here if needed
+      //pthread_mutex_lock(&gInitMutex);
+      //pthread_mutex_unlock(&gInitMutex);
+   }
+
+   if (res == EGL_TRUE) {
+      if (major != NULL) *major = VERSION_MAJOR;
+      if (minor != NULL) *minor = VERSION_MINOR;
+   }
+   return res;
+}
+
+EGLBoolean eglTerminate(EGLDisplay dpy)
+{
+   puts("agl2:eglTerminate");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   EGLBoolean res = EGL_TRUE;
+   egl_display_t& d = egl_display_t::get_display(dpy);
+   if (android_atomic_dec(&d.initialized) == 1) {
+      // TODO: destroy all resources (surfaces, contexts, etc...)
+      //pthread_mutex_lock(&gInitMutex);
+      //pthread_mutex_unlock(&gInitMutex);
+   }
+   return res;
+}
+
+// ----------------------------------------------------------------------------
+// configuration
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglGetConfigs(   EGLDisplay dpy,
+                            EGLConfig *configs,
+                            EGLint config_size, EGLint *num_config)
+{
+   puts("agl2:eglGetConfigs");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   GLint numConfigs = NELEM(gConfigs);
+   if (!configs) {
+      *num_config = numConfigs;
+      return EGL_TRUE;
+   }
+   GLint i;
+   for (i=0 ; i<numConfigs && i<config_size ; i++) {
+      *configs++ = (EGLConfig)i;
+   }
+   *num_config = i;
+   return EGL_TRUE;
+}
+
+static const char * ATTRIBUTE_NAMES [] = {
+   "EGL_BUFFER_SIZE",
+   "EGL_ALPHA_SIZE",
+   "EGL_BLUE_SIZE",
+   "EGL_GREEN_SIZE",
+   "EGL_RED_SIZE",
+   "EGL_DEPTH_SIZE",
+   "EGL_STENCIL_SIZE",
+   "EGL_CONFIG_CAVEAT",
+   "EGL_CONFIG_ID",
+   "EGL_LEVEL",
+   "EGL_MAX_PBUFFER_HEIGHT",
+   "EGL_MAX_PBUFFER_PIXELS",
+   "EGL_MAX_PBUFFER_WIDTH",
+   "EGL_NATIVE_RENDERABLE",
+   "EGL_NATIVE_VISUAL_ID",
+   "EGL_NATIVE_VISUAL_TYPE",
+   "EGL_PRESERVED_RESOURCES",
+   "EGL_SAMPLES",
+   "EGL_SAMPLE_BUFFERS",
+   "EGL_SURFACE_TYPE",
+   "EGL_TRANSPARENT_TYPE",
+   "EGL_TRANSPARENT_BLUE_VALUE",
+   "EGL_TRANSPARENT_GREEN_VALUE",
+   "EGL_TRANSPARENT_RED_VALUE",
+   "EGL_NONE",   /* Attrib list terminator */
+   "EGL_BIND_TO_TEXTURE_RGB",
+   "EGL_BIND_TO_TEXTURE_RGBA",
+   "EGL_MIN_SWAP_INTERVAL",
+   "EGL_MAX_SWAP_INTERVAL",
+   "EGL_LUMINANCE_SIZE",
+   "EGL_ALPHA_MASK_SIZE",
+   "EGL_COLOR_BUFFER_TYPE",
+   "EGL_RENDERABLE_TYPE",
+   "EGL_MATCH_NATIVE_PIXMAP",   /* Pseudo-attribute (not queryable) */
+   "EGL_CONFORMANT",
+};
+
+EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
+                            EGLConfig *configs, EGLint config_size,
+                            EGLint *num_config)
+{
+   puts("agl2:eglChooseConfig");
+   LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   if (ggl_unlikely(num_config==0)) {
+      LOGD("\n***\n***\n num_config==0 \n***\n***\n");
+      return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+   }
+
+   if (ggl_unlikely(attrib_list==0)) {
+      /*
+       * A NULL attrib_list should be treated as though it was an empty
+       * one (terminated with EGL_NONE) as defined in
+       * section 3.4.1 "Querying Configurations" in the EGL specification.
+       */
+      LOGD("\n***\n***\n attrib_list==0 \n***\n***\n");
+      static const EGLint dummy = EGL_NONE;
+      attrib_list = &dummy;
+   }
+
+   for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) {
+      LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]);
+      if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0])
+         LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]);
+   }
+
+   int numAttributes = 0;
+   int numConfigs =  NELEM(gConfigs);
+   uint32_t possibleMatch = (1<<numConfigs)-1;
+   while (possibleMatch && *attrib_list != EGL_NONE) {
+      numAttributes++;
+      EGLint attr = *attrib_list++;
+      EGLint val  = *attrib_list++;
+      for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
+         if (!(possibleMatch & (1<<i)))
+            continue;
+         if (isAttributeMatching(i, attr, val) == 0) {
+            LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val);
+            possibleMatch &= ~(1<<i);
+         }
+      }
+   }
+
+   LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch);
+
+   // now, handle the attributes which have a useful default value
+   for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
+      // see if this attribute was specified, if not, apply its
+      // default value
+      if (binarySearch<config_pair_t>(
+               (config_pair_t const*)attrib_list,
+               0, numAttributes-1,
+               config_defaults[j].key) < 0) {
+         for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
+            if (!(possibleMatch & (1<<i)))
+               continue;
+            if (isAttributeMatching(i,
+                                    config_defaults[j].key,
+                                    config_defaults[j].value) == 0) {
+               possibleMatch &= ~(1<<i);
+            }
+         }
+      }
+   }
+
+   // return the configurations found
+   int n=0;
+   if (possibleMatch) {
+      if (configs) {
+         for (int i=0 ; config_size && i<numConfigs ; i++) {
+            if (possibleMatch & (1<<i)) {
+               *configs++ = (EGLConfig)i;
+               config_size--;
+               n++;
+            }
+         }
+      } else {
+         for (int i=0 ; i<numConfigs ; i++) {
+            if (possibleMatch & (1<<i)) {
+               n++;
+            }
+         }
+      }
+   }
+   *num_config = n;
+   LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config);
+   return EGL_TRUE;
+}
+
+EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+                              EGLint attribute, EGLint *value)
+{
+   puts("agl2:eglGetConfigAttrib");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   return getConfigAttrib(dpy, config, attribute, value);
+}
+
+// ----------------------------------------------------------------------------
+// surfaces
+// ----------------------------------------------------------------------------
+
+EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
+                                    NativeWindowType window,
+                                    const EGLint *attrib_list)
+{
+   puts("agl2:eglCreateWindowSurface");
+   return createWindowSurface(dpy, config, window, attrib_list);
+}
+
+EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
+                                    NativePixmapType pixmap,
+                                    const EGLint *attrib_list)
+{
+   puts("agl2:eglCreatePixmapSurface");
+   return createPixmapSurface(dpy, config, pixmap, attrib_list);
+}
+
+EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
+                                    const EGLint *attrib_list)
+{
+   puts("agl2:eglCreatePbufferSurface");
+   return createPbufferSurface(dpy, config, attrib_list);
+}
+
+EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
+{
+   puts("agl2:eglDestroySurface");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   if (eglSurface != EGL_NO_SURFACE) {
+      egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
+      if (!surface->isValid())
+         return setError(EGL_BAD_SURFACE, EGL_FALSE);
+      if (surface->dpy != dpy)
+         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+      if (surface->ctx) {
+         // FIXME: this surface is current check what the spec says
+         surface->disconnect();
+         surface->ctx = 0;
+      }
+      delete surface;
+   }
+   return EGL_TRUE;
+}
+
+EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
+                            EGLint attribute, EGLint *value)
+{
+   puts("agl2:eglQuerySurface");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
+   if (!surface->isValid())
+      return setError(EGL_BAD_SURFACE, EGL_FALSE);
+   if (surface->dpy != dpy)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   EGLBoolean ret = EGL_TRUE;
+   switch (attribute) {
+   case EGL_CONFIG_ID:
+      ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
+      break;
+   case EGL_WIDTH:
+      *value = surface->getWidth();
+      break;
+   case EGL_HEIGHT:
+      *value = surface->getHeight();
+      break;
+   case EGL_LARGEST_PBUFFER:
+      // not modified for a window or pixmap surface
+      break;
+   case EGL_TEXTURE_FORMAT:
+      *value = EGL_NO_TEXTURE;
+      break;
+   case EGL_TEXTURE_TARGET:
+      *value = EGL_NO_TEXTURE;
+      break;
+   case EGL_MIPMAP_TEXTURE:
+      *value = EGL_FALSE;
+      break;
+   case EGL_MIPMAP_LEVEL:
+      *value = 0;
+      break;
+   case EGL_RENDER_BUFFER:
+      // TODO: return the real RENDER_BUFFER here
+      *value = EGL_BACK_BUFFER;
+      break;
+   case EGL_HORIZONTAL_RESOLUTION:
+      // pixel/mm * EGL_DISPLAY_SCALING
+      *value = surface->getHorizontalResolution();
+      break;
+   case EGL_VERTICAL_RESOLUTION:
+      // pixel/mm * EGL_DISPLAY_SCALING
+      *value = surface->getVerticalResolution();
+      break;
+   case EGL_PIXEL_ASPECT_RATIO: {
+      // w/h * EGL_DISPLAY_SCALING
+      int wr = surface->getHorizontalResolution();
+      int hr = surface->getVerticalResolution();
+      *value = (wr * EGL_DISPLAY_SCALING) / hr;
+   }
+   break;
+   case EGL_SWAP_BEHAVIOR:
+      *value = surface->getSwapBehavior();
+      break;
+   default:
+      ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+   }
+   return ret;
+}
+
+EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
+                            EGLContext share_list, const EGLint *attrib_list)
+{
+   puts("agl2:eglCreateContext");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+
+   GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t));
+   if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+
+   //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
+   egl_context_t * c = &gl->egl;
+   c->flags = egl_context_t::NEVER_CURRENT;
+   c->dpy = dpy;
+   c->config = config;
+   c->read = 0;
+   c->draw = 0;
+   
+   c->frame = 0;
+   c->lastSwapTime = clock();
+   c->accumulateSeconds = 0;
+   return (EGLContext)gl;
+}
+
+EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+   puts("agl2:eglDestroyContext");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   egl_context_t* c = egl_context_t::context(ctx);
+   if (c->flags & egl_context_t::IS_CURRENT)
+      setGlThreadSpecific(0);
+   //ogles_uninit((GLES2Context*)ctx);
+   delete (GLES2Context*)ctx;
+   return EGL_TRUE;
+}
+
+EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
+                            EGLSurface read, EGLContext ctx)
+{
+   puts("agl2:eglMakeCurrent");
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   if (draw) {
+      egl_surface_t* s = (egl_surface_t*)draw;
+      if (!s->isValid())
+         return setError(EGL_BAD_SURFACE, EGL_FALSE);
+      if (s->dpy != dpy)
+         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+      // TODO: check that draw is compatible with the context
+   }
+   if (read && read!=draw) {
+      egl_surface_t* s = (egl_surface_t*)read;
+      if (!s->isValid())
+         return setError(EGL_BAD_SURFACE, EGL_FALSE);
+      if (s->dpy != dpy)
+         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+      // TODO: check that read is compatible with the context
+   }
+
+   EGLContext current_ctx = EGL_NO_CONTEXT;
+
+   if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
+      return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+   if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
+      return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+   if (ctx == EGL_NO_CONTEXT) {
+      // if we're detaching, we need the current context
+      current_ctx = (EGLContext)getGlThreadSpecific();
+   } else {
+      egl_context_t* c = egl_context_t::context(ctx);
+      egl_surface_t* d = (egl_surface_t*)draw;
+      egl_surface_t* r = (egl_surface_t*)read;
+      if ((d && d->ctx && d->ctx != ctx) ||
+            (r && r->ctx && r->ctx != ctx)) {
+         // one of the surface is bound to a context in another thread
+         return setError(EGL_BAD_ACCESS, EGL_FALSE);
+      }
+   }
+
+   GLES2Context* gl = (GLES2Context*)ctx;
+   if (makeCurrent(gl) == 0) {
+      if (ctx) {
+         egl_context_t* c = egl_context_t::context(ctx);
+         egl_surface_t* d = (egl_surface_t*)draw;
+         egl_surface_t* r = (egl_surface_t*)read;
+
+         if (c->draw) {
+            egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
+            s->disconnect();
+         }
+         if (c->read) {
+            // FIXME: unlock/disconnect the read surface too
+         }
+
+         c->draw = draw;
+         c->read = read;
+
+         if (c->flags & egl_context_t::NEVER_CURRENT) {
+            c->flags &= ~egl_context_t::NEVER_CURRENT;
+            GLint w = 0;
+            GLint h = 0;
+            if (draw) {
+               w = d->getWidth();
+               h = d->getHeight();
+            }
+            gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h);
+            //ogles_surfaceport(gl, 0, 0);
+            //ogles_viewport(gl, 0, 0, w, h);
+            //ogles_scissor(gl, 0, 0, w, h);
+         }
+         if (d) {
+            if (d->connect() == EGL_FALSE) {
+               return EGL_FALSE;
+            }
+            d->ctx = ctx;
+            d->bindDrawSurface(gl);
+         }
+         if (r) {
+            // FIXME: lock/connect the read surface too
+            r->ctx = ctx;
+            r->bindReadSurface(gl);
+         }
+      } else {
+         // if surfaces were bound to the context bound to this thread
+         // mark then as unbound.
+         if (current_ctx) {
+            egl_context_t* c = egl_context_t::context(current_ctx);
+            egl_surface_t* d = (egl_surface_t*)c->draw;
+            egl_surface_t* r = (egl_surface_t*)c->read;
+            if (d) {
+               c->draw = 0;
+               d->ctx = EGL_NO_CONTEXT;
+               d->disconnect();
+            }
+            if (r) {
+               c->read = 0;
+               r->ctx = EGL_NO_CONTEXT;
+               // FIXME: unlock/disconnect the read surface too
+            }
+         }
+      }
+      return EGL_TRUE;
+   }
+   return setError(EGL_BAD_ACCESS, EGL_FALSE);
+}
+
+EGLContext eglGetCurrentContext(void)
+{
+   // eglGetCurrentContext returns the current EGL rendering context,
+   // as specified by eglMakeCurrent. If no context is current,
+   // EGL_NO_CONTEXT is returned.
+   return (EGLContext)getGlThreadSpecific();
+}
+
+EGLSurface eglGetCurrentSurface(EGLint readdraw)
+{
+   // eglGetCurrentSurface returns the read or draw surface attached
+   // to the current EGL rendering context, as specified by eglMakeCurrent.
+   // If no context is current, EGL_NO_SURFACE is returned.
+   EGLContext ctx = (EGLContext)getGlThreadSpecific();
+   if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
+   egl_context_t* c = egl_context_t::context(ctx);
+   if (readdraw == EGL_READ) {
+      return c->read;
+   } else if (readdraw == EGL_DRAW) {
+      return c->draw;
+   }
+   return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+}
+
+EGLDisplay eglGetCurrentDisplay(void)
+{
+   // eglGetCurrentDisplay returns the current EGL display connection
+   // for the current EGL rendering context, as specified by eglMakeCurrent.
+   // If no context is current, EGL_NO_DISPLAY is returned.
+   EGLContext ctx = (EGLContext)getGlThreadSpecific();
+   if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
+   egl_context_t* c = egl_context_t::context(ctx);
+   return c->dpy;
+}
+
+EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
+                            EGLint attribute, EGLint *value)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   egl_context_t* c = egl_context_t::context(ctx);
+   switch (attribute) {
+   case EGL_CONFIG_ID:
+      // Returns the ID of the EGL frame buffer configuration with
+      // respect to which the context was created
+      return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
+   }
+   return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+}
+
+EGLBoolean eglWaitGL(void)
+{
+   return EGL_TRUE;
+}
+
+EGLBoolean eglWaitNative(EGLint engine)
+{
+   return EGL_TRUE;
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+   if (!d->isValid())
+      return setError(EGL_BAD_SURFACE, EGL_FALSE);
+   if (d->dpy != dpy)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   // post the surface
+   d->swapBuffers();
+
+   // if it's bound to a context, update the buffer
+   if (d->ctx != EGL_NO_CONTEXT) {
+      d->bindDrawSurface((GLES2Context*)d->ctx);
+      // if this surface is also the read surface of the context
+      // it is bound to, make sure to update the read buffer as well.
+      // The EGL spec is a little unclear about this.
+      egl_context_t* c = egl_context_t::context(d->ctx);
+      if (c->read == draw) {
+         d->bindReadSurface((GLES2Context*)d->ctx);
+      }
+      clock_t time = clock();
+      float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC;
+      c->accumulateSeconds += elapsed;
+      c->frame++;
+//      LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000);
+      if (20 == c->frame) {
+         float avg = c->accumulateSeconds / c->frame;
+         LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*",
+              c->frame, 1 / avg, avg * 1000);
+         c->frame = 0;
+         c->accumulateSeconds = 0;
+      }
+      c->lastSwapTime = time;
+   }
+
+   return EGL_TRUE;
+}
+
+EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
+                            NativePixmapType target)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   // TODO: eglCopyBuffers()
+   return EGL_FALSE;
+}
+
+EGLint eglGetError(void)
+{
+   return getError();
+}
+
+const char* eglQueryString(EGLDisplay dpy, EGLint name)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, (const char*)0);
+
+   switch (name) {
+   case EGL_VENDOR:
+      return gVendorString;
+   case EGL_VERSION:
+      return gVersionString;
+   case EGL_EXTENSIONS:
+      return gExtensionsString;
+   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)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   // TODO: eglSurfaceAttrib()
+   return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+}
+
+EGLBoolean eglBindTexImage(
+   EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   // TODO: eglBindTexImage()
+   return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+}
+
+EGLBoolean eglReleaseTexImage(
+   EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   // TODO: eglReleaseTexImage()
+   return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+}
+
+EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   // TODO: eglSwapInterval()
+   return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// EGL 1.2
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglBindAPI(EGLenum api)
+{
+   if (api != EGL_OPENGL_ES_API)
+      return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+   return EGL_TRUE;
+}
+
+EGLenum eglQueryAPI(void)
+{
+   return EGL_OPENGL_ES_API;
+}
+
+EGLBoolean eglWaitClient(void)
+{
+   glFinish();
+   return EGL_TRUE;
+}
+
+EGLBoolean eglReleaseThread(void)
+{
+   // TODO: eglReleaseThread()
+   return EGL_TRUE;
+}
+
+EGLSurface eglCreatePbufferFromClientBuffer(
+   EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+   EGLConfig config, const EGLint *attrib_list)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+   // TODO: eglCreatePbufferFromClientBuffer()
+   return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+}
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 3
+// ----------------------------------------------------------------------------
+
+void (*eglGetProcAddress (const char *procname))()
+{
+   extention_map_t const * const map = gExtentionMap;
+   for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
+      if (!strcmp(procname, map[i].name)) {
+         return map[i].address;
+      }
+   }
+   return NULL;
+}
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+                             const EGLint *attrib_list)
+{
+   EGLBoolean result = EGL_FALSE;
+   return result;
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+   EGLBoolean result = EGL_FALSE;
+   return result;
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+                              EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+      return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+   }
+   if (ctx != EGL_NO_CONTEXT) {
+      return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+   }
+   if (target != EGL_NATIVE_BUFFER_ANDROID) {
+      return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+   }
+
+   android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
+
+   if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+      return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+   if (native_buffer->common.version != sizeof(android_native_buffer_t))
+      return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+   switch (native_buffer->format) {
+   case HAL_PIXEL_FORMAT_RGBA_8888:
+   case HAL_PIXEL_FORMAT_RGBX_8888:
+   case HAL_PIXEL_FORMAT_RGB_888:
+   case HAL_PIXEL_FORMAT_RGB_565:
+   case HAL_PIXEL_FORMAT_BGRA_8888:
+   case HAL_PIXEL_FORMAT_RGBA_5551:
+   case HAL_PIXEL_FORMAT_RGBA_4444:
+      break;
+   default:
+      return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+   }
+
+   native_buffer->common.incRef(&native_buffer->common);
+   return (EGLImageKHR)native_buffer;
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+   }
+
+   android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
+
+   if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+      return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+   if (native_buffer->common.version != sizeof(android_native_buffer_t))
+      return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+   native_buffer->common.decRef(&native_buffer->common);
+
+   return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+                                      EGLint left, EGLint top, EGLint width, EGLint height)
+{
+   if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+   if (!d->isValid())
+      return setError(EGL_BAD_SURFACE, EGL_FALSE);
+   if (d->dpy != dpy)
+      return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+   // post the surface
+   d->setSwapRectangle(left, top, width, height);
+
+   return EGL_TRUE;
+}
diff --git a/opengl/libagl2/src/get.cpp b/opengl/libagl2/src/get.cpp
new file mode 100644
index 0000000..13c28ce
--- /dev/null
+++ b/opengl/libagl2/src/get.cpp
@@ -0,0 +1,79 @@
+#include "gles2context.h"
+
+static char const * const gVendorString     = "Android";
+static char const * const gRendererString   = "Android PixelFlinger2 0.0";
+static char const * const gVersionString    = "OpenGL ES 2.0";
+static char const * const gExtensionsString =
+//   "GL_OES_byte_coordinates "              // OK
+//   "GL_OES_fixed_point "                   // OK
+//   "GL_OES_single_precision "              // OK
+//   "GL_OES_read_format "                   // OK
+//   "GL_OES_compressed_paletted_texture "   // OK
+//   "GL_OES_draw_texture "                  // OK
+//   "GL_OES_matrix_get "                    // OK
+//   "GL_OES_query_matrix "                  // OK
+//   //        "GL_OES_point_size_array "              // TODO
+//   //        "GL_OES_point_sprite "                  // TODO
+//   "GL_OES_EGL_image "                     // OK
+//#ifdef GL_OES_compressed_ETC1_RGB8_texture
+//   "GL_OES_compressed_ETC1_RGB8_texture "  // OK
+//#endif
+//   "GL_ARB_texture_compression "           // OK
+//   "GL_ARB_texture_non_power_of_two "      // OK
+//   "GL_ANDROID_user_clip_plane "           // OK
+//   "GL_ANDROID_vertex_buffer_object "      // OK
+//   "GL_ANDROID_generate_mipmap "           // OK
+   ""
+   ;
+
+void glGetIntegerv(GLenum pname, GLint* params)
+{
+   switch (pname) {
+   case GL_MAX_TEXTURE_SIZE :
+      *params = 4096; // limit is in precision of texcoord calculation, which uses 16.16
+      break;
+   case GL_MAX_VERTEX_ATTRIBS:
+      *params = GGL_MAXVERTEXATTRIBS;
+      break;
+   case GL_MAX_VERTEX_UNIFORM_VECTORS:
+      *params = GGL_MAXVERTEXUNIFORMVECTORS;
+      break;
+   case GL_MAX_VARYING_VECTORS:
+      *params = GGL_MAXVARYINGVECTORS;
+      break;
+   case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+      *params = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS;
+      break;
+   case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+      *params = GGL_MAXVERTEXTEXTUREIMAGEUNITS;
+      break;
+   case GL_MAX_TEXTURE_IMAGE_UNITS:
+      *params = GGL_MAXTEXTUREIMAGEUNITS;
+      break;
+   case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+      *params = GGL_MAXFRAGMENTUNIFORMVECTORS;
+      break;
+   case GL_ALIASED_LINE_WIDTH_RANGE:
+      *params = 1; // TODO: not implemented
+      break;
+   default:
+      LOGD("agl2: glGetIntegerv 0x%.4X", pname);
+      assert(0);
+   }
+}
+
+const GLubyte* glGetString(GLenum name)
+{
+   switch (name) {
+   case GL_VENDOR:
+      return (const GLubyte*)gVendorString;
+   case GL_RENDERER:
+      return (const GLubyte*)gRendererString;
+   case GL_VERSION:
+      return (const GLubyte*)gVersionString;
+   case GL_EXTENSIONS:
+      return (const GLubyte*)gExtensionsString;
+   }
+   assert(0); //(c, GL_INVALID_ENUM);
+   return 0;
+}
diff --git a/opengl/libagl2/src/gles2context.h b/opengl/libagl2/src/gles2context.h
new file mode 100644
index 0000000..cec0340
--- /dev/null
+++ b/opengl/libagl2/src/gles2context.h
@@ -0,0 +1,166 @@
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+
+#include <stdio.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 <pthread.h>
+
+#include <cutils/log.h>
+
+#include <assert.h>
+
+#ifdef __arm__
+#ifndef __location__
+#define __HIERALLOC_STRING_0__(s)   #s
+#define __HIERALLOC_STRING_1__(s)   __HIERALLOC_STRING_0__(s)
+#define __HIERALLOC_STRING_2__      __HIERALLOC_STRING_1__(__LINE__)
+#define __location__                __FILE__ ":" __HIERALLOC_STRING_2__
+#endif
+#undef assert
+#define assert(EXPR) { do { if (!(EXPR)) {LOGD("\n*\n*\n*\n* assert fail: '"#EXPR"' at "__location__"\n*\n*\n*\n*"); exit(EXIT_FAILURE); } } while (false); }
+//#define printf LOGD
+#else // #ifdef __arm__
+//#define LOGD printf
+#endif // #ifdef __arm__
+
+
+#include <pixelflinger2/pixelflinger2_format.h>
+#include <pixelflinger2/pixelflinger2.h>
+
+#include <map>
+
+typedef uint8_t                 GGLubyte;               // ub
+
+#define ggl_likely(x)   __builtin_expect(!!(x), 1)
+#define ggl_unlikely(x) __builtin_expect(!!(x), 0)
+
+#undef NELEM
+#define NELEM(x) (sizeof(x)/sizeof(*(x)))
+
+template<typename T>
+inline T max(T a, T b)
+{
+   return a<b ? b : a;
+}
+
+template<typename T>
+inline T min(T a, T b)
+{
+   return a<b ? a : b;
+}
+
+struct egl_context_t {
+   enum {
+      IS_CURRENT      =   0x00010000,
+      NEVER_CURRENT   =   0x00020000
+   };
+   uint32_t            flags;
+   EGLDisplay          dpy;
+   EGLConfig           config;
+   EGLSurface          read;
+   EGLSurface          draw;
+
+   unsigned frame;
+   clock_t lastSwapTime;
+   float accumulateSeconds;
+   
+   static inline egl_context_t* context(EGLContext ctx);
+};
+
+struct GLES2Context;
+
+#ifdef HAVE_ANDROID_OS
+#include <bionic_tls.h>
+// We have a dedicated TLS slot in bionic
+inline void setGlThreadSpecific(GLES2Context *value)
+{
+   ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)value;
+}
+inline GLES2Context* getGlThreadSpecific()
+{
+   return (GLES2Context *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]);
+}
+#else
+extern pthread_key_t gGLKey;
+inline void setGlThreadSpecific(GLES2Context *value)
+{
+   pthread_setspecific(gGLKey, value);
+}
+inline GLES2Context* getGlThreadSpecific()
+{
+   return static_cast<GLES2Context*>(pthread_getspecific(gGLKey));
+}
+#endif
+
+struct VBO {
+   unsigned size;
+   GLenum usage;
+   void * data;
+};
+
+struct GLES2Context {
+   GGLContext rasterizer;
+   egl_context_t egl;
+   GGLInterface * iface; // shortcut to &rasterizer.interface
+
+   struct VertexState {
+      struct VertAttribPointer {
+         unsigned size; // number of values per vertex
+         GLenum type;  // data type
+         unsigned stride; // bytes
+         const void * ptr;
+bool normalized :
+         1;
+bool enabled :
+         1;
+      } attribs [GGL_MAXVERTEXATTRIBS];
+
+      VBO * vbo, * indices;
+      std::map<GLuint, VBO *> vbos;
+      GLuint free;
+
+      Vector4 defaultAttribs [GGL_MAXVERTEXATTRIBS];
+   } vert;
+
+   struct TextureState {
+      GGLTexture * tmus[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS];
+      int sampler2tmu[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]; // sampler2tmu[sampler] is index of tmu, -1 means not used
+      unsigned active;
+      std::map<GLuint, GGLTexture *> textures;
+      GLuint free; // first possible free name
+      GGLTexture * tex2D, * texCube; // default textures
+      unsigned unpack;
+      
+      void UpdateSampler(GGLInterface * iface, unsigned tmu);
+   } tex;
+
+   GLES2Context();
+   void InitializeTextures();
+   void InitializeVertices();
+
+   ~GLES2Context();
+   void UninitializeTextures();
+   void UninitializeVertices();
+
+   static inline GLES2Context* get() {
+      return getGlThreadSpecific();
+   }
+};
+
+inline egl_context_t* egl_context_t::context(EGLContext ctx)
+{
+   GLES2Context* const gl = static_cast<GLES2Context*>(ctx);
+   return static_cast<egl_context_t*>(&gl->egl);
+}
+
+#define GLES2_GET_CONTEXT(ctx) GLES2Context * ctx = GLES2Context::get(); \
+                                 /*puts(__FUNCTION__);*/
+#define GLES2_GET_CONST_CONTEXT(ctx) GLES2Context * ctx = GLES2Context::get(); \
+                                       /*puts(__FUNCTION__);*/
diff --git a/opengl/libagl2/src/shader.cpp b/opengl/libagl2/src/shader.cpp
new file mode 100644
index 0000000..076e388
--- /dev/null
+++ b/opengl/libagl2/src/shader.cpp
@@ -0,0 +1,191 @@
+#include "gles2context.h"
+
+//#undef LOGD
+//#define LOGD(...)
+
+static inline GLuint s2n(gl_shader * s)
+{
+   return (GLuint)s ^ 0xaf3c532d;
+}
+
+static inline gl_shader * n2s(GLuint n)
+{
+   return (gl_shader *)(n ^ 0xaf3c532d);
+}
+
+static inline GLuint p2n(gl_shader_program * p)
+{
+   return (GLuint)p ^ 0x04dc18f9;
+}
+
+static inline gl_shader_program * n2p(GLuint n)
+{
+   return (gl_shader_program *)(n ^ 0x04dc18f9);
+}
+
+void glAttachShader(GLuint program, GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderAttach(ctx->iface, n2p(program), n2s(shader));
+}
+
+void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderAttributeBind(n2p(program), index, name);
+//   assert(0);
+}
+
+GLuint glCreateShader(GLenum type)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   return s2n(ctx->iface->ShaderCreate(ctx->iface, type));
+}
+
+GLuint glCreateProgram(void)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   return  p2n(ctx->iface->ShaderProgramCreate(ctx->iface));
+}
+
+void glCompileShader(GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderCompile(ctx->iface, n2s(shader), NULL, NULL);
+}
+
+void glDeleteProgram(GLuint program)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderProgramDelete(ctx->iface, n2p(program));
+}
+
+void glDeleteShader(GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderDelete(ctx->iface, n2s(shader));
+}
+
+void glDetachShader(GLuint program, GLuint shader)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderDetach(ctx->iface, n2p(program), n2s(shader));
+}
+
+GLint glGetAttribLocation(GLuint program, const GLchar* name)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   GLint location = ctx->iface->ShaderAttributeLocation(n2p(program), name);
+//   LOGD("\n*\n*\n* agl2: glGetAttribLocation program=%u name=%s location=%d \n*\n*",
+//        program, name, location);
+   return location;
+}
+
+void glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderProgramGetiv(n2p(program), pname, params);
+   LOGD("agl2: glGetProgramiv 0x%.4X=%d \n", pname, *params);
+}
+
+void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderProgramGetInfoLog(n2p(program), bufsize, length, infolog);
+}
+
+void glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderGetiv(n2s(shader), pname, params);
+   LOGD("agl2: glGetShaderiv 0x%.4X=%d \n", pname, *params);
+}
+
+void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderGetInfoLog(n2s(shader), bufsize, length, infolog);
+}
+
+int glGetUniformLocation(GLuint program, const GLchar* name)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   return ctx->iface->ShaderUniformLocation(n2p(program), name);
+}
+
+void glLinkProgram(GLuint program)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   GLboolean linked = ctx->iface->ShaderProgramLink(n2p(program), NULL);
+   assert(linked);
+}
+
+void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ShaderSource(n2s(shader), count, string, length);
+}
+
+void glUniform1f(GLint location, GLfloat x)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   int sampler = ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, &x, GL_FLOAT);
+   assert(0 > sampler); // should be assigning to sampler
+}
+
+void glUniform1i(GLint location, GLint x)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   const float params[1] = {x};
+   int sampler = ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_INT);
+   if (0 <= sampler) {
+//      LOGD("\n*\n* agl2: glUniform1i updated sampler=%d tmu=%d location=%d\n*", sampler, x, location);
+      assert(0 <= x && GGL_MAXCOMBINEDTEXTUREIMAGEUNITS > x);
+//      LOGD("tmu%u: format=0x%.2X w=%u h=%u levels=%p", x, ctx->tex.tmus[x]->format, 
+//         ctx->tex.tmus[x]->width, ctx->tex.tmus[x]->height, ctx->tex.tmus[x]->format);
+      ctx->tex.sampler2tmu[sampler] = x;
+      ctx->tex.UpdateSampler(ctx->iface, x);
+   }
+}
+
+void glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   const float params[4] = {x, y};
+   ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_FLOAT_VEC2);
+}
+
+void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   const float params[4] = {x, y, z, w};
+//   LOGD("agl2: glUniform4f location=%d %f,%f,%f,%f", location, x, y, z, w);
+   ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_FLOAT_VEC4);
+}
+
+void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   const gl_shader_program * program = ctx->rasterizer.CurrentProgram;
+//   if (strstr(program->Shaders[MESA_SHADER_FRAGMENT]->Source, ").a;")) {
+//   LOGD("agl2: glUniformMatrix4fv location=%d count=%d transpose=%d", location, count, transpose);
+//   for (unsigned i = 0; i < 4; i++)
+//      LOGD("agl2: glUniformMatrix4fv %.2f \t %.2f \t %.2f \t %.2f", value[i * 4 + 0],
+//           value[i * 4 + 1], value[i * 4 + 2], value[i * 4 + 3]);
+//   }
+   ctx->iface->ShaderUniformMatrix(ctx->rasterizer.CurrentProgram, 4, 4, location, count, transpose, value);
+//   while (true)
+//      ;
+//   assert(0);
+}
+
+void glUseProgram(GLuint program)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("\n*\n*\n* agl2: glUseProgram %d \n*\n*\n*", program);
+   ctx->iface->ShaderUse(ctx->iface, n2p(program));
+   ctx->iface->ShaderUniformGetSamplers(n2p(program), ctx->tex.sampler2tmu);
+   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
+      if (0 <= ctx->tex.sampler2tmu[i])
+         ctx->iface->SetSampler(ctx->iface, i, ctx->tex.tmus[ctx->tex.sampler2tmu[i]]);
+}
diff --git a/opengl/libagl2/src/state.cpp b/opengl/libagl2/src/state.cpp
new file mode 100644
index 0000000..22e73fa
--- /dev/null
+++ b/opengl/libagl2/src/state.cpp
@@ -0,0 +1,129 @@
+#include "gles2context.h"
+
+GLES2Context::GLES2Context()
+{
+   memset(this, 0, sizeof *this);
+
+   assert((void *)&rasterizer == &rasterizer.interface);
+   InitializeGGLState(&rasterizer.interface);
+   iface = &rasterizer.interface;
+   printf("gl->rasterizer.PickScanLine(%p) = %p \n", &rasterizer.PickScanLine, rasterizer.PickScanLine);
+   assert(rasterizer.PickRaster);
+   assert(rasterizer.PickScanLine);
+
+   InitializeTextures();
+   InitializeVertices();
+}
+
+GLES2Context::~GLES2Context()
+{
+   UninitializeTextures();
+   UninitializeVertices();
+   UninitializeGGLState(&rasterizer.interface);
+}
+
+void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendColor(ctx->iface, red, green, blue, alpha);
+}
+
+void glBlendEquation( GLenum mode )
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendEquationSeparate(ctx->iface, mode, mode);
+}
+
+void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendEquationSeparate(ctx->iface, modeRGB, modeAlpha);
+}
+
+void glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendFuncSeparate(ctx->iface, sfactor, dfactor, sfactor, dfactor);
+}
+
+void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->BlendFuncSeparate(ctx->iface, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void glClear(GLbitfield mask)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->Clear(ctx->iface, mask);
+}
+
+void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ClearColor(ctx->iface, red, green, blue, alpha);
+}
+
+void glClearDepthf(GLclampf depth)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ClearDepthf(ctx->iface, depth);
+}
+
+void glClearStencil(GLint s)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->ClearStencil(ctx->iface, s);
+}
+
+void glCullFace(GLenum mode)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->CullFace(ctx->iface, mode);
+}
+
+void glDisable(GLenum cap)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->EnableDisable(ctx->iface, cap, false);
+}
+
+void glEnable(GLenum cap)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->EnableDisable(ctx->iface, cap, true);
+}
+
+void glFinish(void)
+{
+   // do nothing
+}
+
+void glFrontFace(GLenum mode)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->iface->FrontFace(ctx->iface, mode);
+}
+
+void glFlush(void)
+{
+   // do nothing
+}
+
+void glHint(GLenum target, GLenum mode)
+{
+   // do nothing
+}
+
+void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+//   LOGD("agl2: glScissor not implemented x=%d y=%d width=%d height=%d", x, y, width, height);
+   //CALL_GL_API(glScissor, x, y, width, height);
+}
+
+void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glViewport x=%d y=%d width=%d height=%d", x, y, width, height);
+   ctx->iface->Viewport(ctx->iface, x, y, width, height);
+}
diff --git a/opengl/libagl2/src/texture.cpp b/opengl/libagl2/src/texture.cpp
new file mode 100644
index 0000000..4de1f16
--- /dev/null
+++ b/opengl/libagl2/src/texture.cpp
@@ -0,0 +1,534 @@
+#include "gles2context.h"
+
+//#undef LOGD
+//#define LOGD(...) 
+
+#define API_ENTRY
+#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0);
+#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0;
+
+static inline GGLTexture * AllocTexture()
+{
+   GGLTexture * tex = (GGLTexture *)calloc(1, sizeof(GGLTexture));
+   tex->minFilter = GGLTexture::GGL_LINEAR; // should be NEAREST_ MIPMAP_LINEAR
+   tex->magFilter = GGLTexture::GGL_LINEAR;
+   return tex;
+}
+
+void GLES2Context::InitializeTextures()
+{
+   tex.textures = std::map<GLuint, GGLTexture *>(); // the entire struct has been zeroed in constructor
+   tex.tex2D = AllocTexture();
+   tex.textures[GL_TEXTURE_2D] = tex.tex2D;
+   tex.texCube = AllocTexture();
+   tex.textures[GL_TEXTURE_CUBE_MAP] = tex.texCube;
+   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) {
+      tex.tmus[i] = NULL;
+      tex.sampler2tmu[i] = NULL;
+   }
+
+   tex.active = 0;
+
+   tex.free = max(GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP) + 1;
+
+   tex.tex2D->format = GGL_PIXEL_FORMAT_RGBA_8888;
+   tex.tex2D->type = GL_TEXTURE_2D;
+   tex.tex2D->levelCount = 1;
+   tex.tex2D->wrapS = tex.tex2D->wrapT = GGLTexture::GGL_REPEAT;
+   tex.tex2D->minFilter = tex.tex2D->magFilter = GGLTexture::GGL_NEAREST;
+   tex.tex2D->width = tex.tex2D->height = 1;
+   tex.tex2D->levels = malloc(4);
+   *(unsigned *)tex.tex2D->levels = 0xff000000;
+
+
+   tex.texCube->format = GGL_PIXEL_FORMAT_RGBA_8888;
+   tex.texCube->type = GL_TEXTURE_CUBE_MAP;
+   tex.texCube->levelCount = 1;
+   tex.texCube->wrapS = tex.texCube->wrapT = GGLTexture::GGL_REPEAT;
+   tex.texCube->minFilter = tex.texCube->magFilter = GGLTexture::GGL_NEAREST;
+   tex.texCube->width = tex.texCube->height = 1;
+   tex.texCube->levels = malloc(4 * 6);
+   static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
+                                 0xff00ffff, 0xffffff00, 0xffff00ff
+                                };
+   memcpy(tex.texCube->levels, texels, sizeof texels);
+
+   //texture.levelCount = GenerateMipmaps(texture.levels, texture.width, texture.height);
+
+   //    static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
+   //    0xff00ffff, 0xffffff00, 0xffff00ff};
+   //    memcpy(texture.levels[0], texels, sizeof texels);
+   //    texture.format = GGL_PIXEL_FORMAT_RGBA_8888;
+   //    texture.width = texture.height = 1;
+   //texture.height /= 6;
+   //texture.type = GL_TEXTURE_CUBE_MAP;
+   
+   tex.unpack = 4;
+}
+
+void GLES2Context::TextureState::UpdateSampler(GGLInterface * iface, unsigned tmu)
+{
+   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
+      if (tmu == sampler2tmu[i])
+         iface->SetSampler(iface, i, tmus[tmu]);
+}
+
+void GLES2Context::UninitializeTextures()
+{
+   for (std::map<GLuint, GGLTexture *>::iterator it = tex.textures.begin(); it != tex.textures.end(); it++) {
+      if (!it->second)
+         continue;
+      free(it->second->levels);
+      free(it->second);
+   }
+}
+
+static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned * bytesPerPixel,
+      GGLPixelFormat * texFormat)
+{
+   switch (format) {
+   case GL_ALPHA:
+      *texFormat = GGL_PIXEL_FORMAT_A_8;
+      *bytesPerPixel = 1;
+      break;
+   case GL_LUMINANCE:
+      *texFormat = GGL_PIXEL_FORMAT_L_8;
+      *bytesPerPixel = 1;
+      break;
+   case GL_LUMINANCE_ALPHA:
+      *texFormat = GGL_PIXEL_FORMAT_LA_88;
+      *bytesPerPixel = 2;
+      break;
+   case GL_RGB:
+      *texFormat = GGL_PIXEL_FORMAT_RGB_888;
+      *bytesPerPixel = 3;
+      break;
+   case GL_RGBA:
+      *texFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+      *bytesPerPixel = 4;
+      break;
+
+      // internal formats to avoid conversion
+   case GL_UNSIGNED_SHORT_5_6_5:
+      *texFormat = GGL_PIXEL_FORMAT_RGB_565;
+      *bytesPerPixel = 2;
+      break;
+
+   default:
+      assert(0);
+      return;
+   }
+}
+
+static inline void CopyTexture(char * dst, const char * src, const unsigned bytesPerPixel,
+                               const unsigned sx, const unsigned sy,  const unsigned sw,
+                               const unsigned dx, const unsigned dy, const unsigned dw,
+                               const unsigned w, const unsigned h)
+{
+   const unsigned bpp = bytesPerPixel;
+   if (dw == sw && dw == w && sx == 0 && dx == 0)
+      memcpy(dst + dy * dw * bpp, src + sy * sw * bpp, w * h * bpp);
+   else
+      for (unsigned y = 0; y < h; y++)
+         memcpy(dst + ((dy + y) * dw + dx) * bpp, src + ((sy + y) * sw + sx) * bpp, w * bpp); 
+}
+
+void glActiveTexture(GLenum texture)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   unsigned index = texture - GL_TEXTURE0;
+   assert(NELEM(ctx->tex.tmus) > index);
+//   LOGD("agl2: glActiveTexture %u", index);
+   ctx->tex.active = index;
+}
+
+void glBindTexture(GLenum target, GLuint texture)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glBindTexture target=0x%.4X texture=%u active=%u", target, texture, ctx->tex.active);
+   std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(texture);
+   GGLTexture * tex = NULL;
+   if (it != ctx->tex.textures.end()) {
+      tex = it->second;
+      if (!tex) {
+         tex = AllocTexture();
+         tex->type = target;
+         it->second = tex;
+//         LOGD("agl2: glBindTexture allocTexture");
+      }
+//      else
+//         LOGD("agl2: glBindTexture bind existing texture");
+      assert(target == tex->type);
+   } else if (0 == texture) {
+      if (GL_TEXTURE_2D == target)
+      {
+         tex = ctx->tex.tex2D;
+//         LOGD("agl2: glBindTexture bind default tex2D");
+      }
+      else if (GL_TEXTURE_CUBE_MAP == target)
+      {
+         tex = ctx->tex.texCube;
+//         LOGD("agl2: glBindTexture bind default texCube");
+      }
+      else
+         assert(0);
+   } else {
+      if (texture <= ctx->tex.free)
+         ctx->tex.free = texture + 1;
+      tex = AllocTexture();
+      tex->type = target;
+      ctx->tex.textures[texture] = tex;
+//      LOGD("agl2: glBindTexture new texture=%u", texture);
+   }
+   ctx->tex.tmus[ctx->tex.active] = tex;
+//   LOGD("agl2: glBindTexture format=0x%.2X w=%u h=%u levels=%p", tex->format,
+//      tex->width, tex->height, tex->levels);
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
+{
+   CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+   CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+
+void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
+                      GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glCopyTexImage2D target=0x%.4X internalformat=0x%.4X", target, internalformat);
+//   LOGD("x=%d y=%d width=%d height=%d border=%d level=%d ", x, y, width, height, border, level);
+   assert(0 == border);
+   assert(0 == level);
+   unsigned bytesPerPixel = 0;
+   GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
+   GetFormatAndBytesPerPixel(internalformat, &bytesPerPixel, &texFormat);
+
+   assert(texFormat == ctx->rasterizer.frameSurface.format);
+//   LOGD("texFormat=0x%.2X bytesPerPixel=%d \n", texFormat, bytesPerPixel);
+   unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
+
+   assert(ctx->tex.tmus[ctx->tex.active]);
+   assert(y + height <= ctx->rasterizer.frameSurface.height);
+   assert(x + width <= ctx->rasterizer.frameSurface.width);
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   tex.width = width;
+   tex.height = height;
+   tex.levelCount = 1;
+   tex.format = texFormat;
+   switch (target) {
+   case GL_TEXTURE_2D:
+      tex.levels = realloc(tex.levels, totalSize);
+      CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel,
+                  x, y, ctx->rasterizer.frameSurface.width, 0, 0, width, width, height);
+      break;
+   default:
+      assert(0);
+      return;
+   }
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   // x, y are src offset
+   // xoffset and yoffset are dst offset
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glCopyTexSubImage2D target=0x%.4X level=%d", target, level);
+//   LOGD("xoffset=%d yoffset=%d x=%d y=%d width=%d height=%d", xoffset, yoffset, x, y, width, height);
+   assert(0 == level);
+
+   unsigned bytesPerPixel = 4;
+   unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
+
+   assert(ctx->tex.tmus[ctx->tex.active]);
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+
+   assert(tex.format == ctx->rasterizer.frameSurface.format);
+   assert(GGL_PIXEL_FORMAT_RGBA_8888 == tex.format);
+
+   const unsigned srcWidth = ctx->rasterizer.frameSurface.width;
+   const unsigned srcHeight = ctx->rasterizer.frameSurface.height;
+
+   assert(x >= 0 && y >= 0);
+   assert(xoffset >= 0 && yoffset >= 0);
+   assert(x + width <= srcWidth);
+   assert(y + height <= srcHeight);
+   assert(xoffset + width <= tex.width);
+   assert(yoffset + height <= tex.height);
+
+   switch (target) {
+   case GL_TEXTURE_2D:
+      CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel,
+                  x, y, srcWidth, xoffset, yoffset, tex.width, width, height);
+      break;
+   default:
+      assert(0);
+      return;
+   }
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void glDeleteTextures(GLsizei n, const GLuint* textures)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(textures[i]);
+      if (it == ctx->tex.textures.end())
+         continue;
+      ctx->tex.free = min(ctx->tex.free, textures[i]);
+      for (unsigned i = 0; i <  GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
+         if (ctx->tex.tmus[i] == it->second) {
+            if (GL_TEXTURE_2D == it->second->type)
+               ctx->tex.tmus[i] = ctx->tex.tex2D;
+            else if (GL_TEXTURE_CUBE_MAP == it->second->type)
+               ctx->tex.tmus[i] = ctx->tex.texCube;
+            else
+               assert(0);
+            ctx->tex.UpdateSampler(ctx->iface, i);
+         }
+      if (it->second) {
+         free(it->second->levels);
+         free(it->second);
+      }
+      ctx->tex.textures.erase(it);
+   }
+}
+
+void glGenTextures(GLsizei n, GLuint* textures)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      textures[i] = 0;
+      for (ctx->tex.free; ctx->tex.free < 0xffffffffu; ctx->tex.free++)
+         if (ctx->tex.textures.find(ctx->tex.free) == ctx->tex.textures.end()) {
+            ctx->tex.textures[ctx->tex.free] = NULL;
+            textures[i] = ctx->tex.free;
+            ctx->tex.free++;
+            break;
+         }
+      assert(textures[i]);
+   }
+}
+
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params)
+{
+   CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params)
+{
+   CALL_GL_API(glGetTexParameteriv, target, pname, params);
+}
+
+GLboolean glIsTexture(GLuint texture)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   if (ctx->tex.textures.find(texture) == ctx->tex.textures.end())
+      return GL_FALSE;
+   else
+      return GL_TRUE;
+}
+
+void glPixelStorei(GLenum pname, GLint param)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   assert(GL_UNPACK_ALIGNMENT == pname);
+   assert(1 == param || 2 == param || 4 == param || 8 == param);
+//   LOGD("\n*\n* agl2: glPixelStorei not implemented pname=0x%.4X param=%d \n*", pname, param);
+   ctx->tex.unpack = param;
+//   CALL_GL_API(glPixelStorei, pname, param);
+}
+void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
+                  GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glTexImage2D internalformat=0x%.4X format=0x%.4X type=0x%.4X \n", internalformat, format, type);
+//   LOGD("width=%d height=%d border=%d level=%d pixels=%p \n", width, height, border, level, pixels);
+   switch (type) {
+   case GL_UNSIGNED_BYTE:
+      break;
+   case GL_UNSIGNED_SHORT_5_6_5:
+      internalformat = format = GL_UNSIGNED_SHORT_5_6_5;
+      assert(4 == ctx->tex.unpack);
+      break;
+   default:
+      assert(0);
+   }
+   assert(internalformat == format);
+   assert(0 == border);
+   if (0 != level) {
+      LOGD("agl2: glTexImage2D level=%d", level);
+      return;
+   }
+   unsigned bytesPerPixel = 0;
+   GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
+   GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat);
+
+   assert(texFormat && bytesPerPixel);
+//   LOGD("texFormat=0x%.2X bytesPerPixel=%d active=%u", texFormat, bytesPerPixel, ctx->tex.active);
+   unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
+
+   assert(ctx->tex.tmus[ctx->tex.active]);
+
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   tex.width = width;
+   tex.height = height;
+   tex.levelCount = 1;
+   tex.format = texFormat;
+
+   switch (target) {
+   case GL_TEXTURE_2D:
+      assert(GL_TEXTURE_2D == ctx->tex.tmus[ctx->tex.active]->type);
+      offset = 0;
+      break;
+      break;
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      assert(GL_TEXTURE_CUBE_MAP == ctx->tex.tmus[ctx->tex.active]->type);
+      assert(width == height);
+      offset = (target - GL_TEXTURE_CUBE_MAP_POSITIVE_X) * size;
+      totalSize = 6 * size;
+      break;
+   default:
+      assert(0);
+      return;
+   }
+
+   tex.levels = realloc(tex.levels, totalSize);
+   if (pixels)
+      CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, 0, 0, width, width, height);
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+
+void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+//   LOGD("agl2: glTexParameterf target=0x%.4X pname=0x%.4X param=%f", target, pname, param);
+   glTexParameteri(target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params)
+{
+   CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("alg2: glTexParameteri target=0x%.0X pname=0x%.4X param=0x%.4X",
+//        target, pname, param);
+   assert(ctx->tex.tmus[ctx->tex.active]);
+   assert(target == ctx->tex.tmus[ctx->tex.active]->type);
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   switch (pname) {
+   case GL_TEXTURE_WRAP_S:
+   case GL_TEXTURE_WRAP_T:
+      GGLTexture::GGLTextureWrap wrap;
+      switch (param) {
+      case GL_REPEAT:
+         wrap = GGLTexture::GGL_REPEAT;
+         break;
+      case GL_CLAMP_TO_EDGE:
+         wrap = GGLTexture::GGL_CLAMP_TO_EDGE;
+         break;
+      case GL_MIRRORED_REPEAT:
+         wrap = GGLTexture::GGL_MIRRORED_REPEAT;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      if (GL_TEXTURE_WRAP_S == pname)
+         tex.wrapS = wrap;
+      else
+         tex.wrapT = wrap;
+      break;
+   case GL_TEXTURE_MIN_FILTER:
+      switch (param) {
+      case GL_NEAREST:
+         tex.minFilter = GGLTexture::GGL_NEAREST;
+         break;
+      case GL_LINEAR:
+         tex.minFilter = GGLTexture::GGL_LINEAR;
+         break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+//         tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_NEAREST;
+         break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+//         tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_LINEAR;
+         break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+//         tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_NEAREST;
+         break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+//         tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_LINEAR;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      break;
+   case GL_TEXTURE_MAG_FILTER:
+      switch (param) {
+      case GL_NEAREST:
+         tex.minFilter = GGLTexture::GGL_NEAREST;
+         break;
+      case GL_LINEAR:
+         tex.minFilter = GGLTexture::GGL_LINEAR;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      break;
+   default:
+      assert(0);
+      return;
+   }
+   // implementation restriction
+   if (tex.magFilter != tex.minFilter)
+      tex.magFilter = tex.minFilter = GGLTexture::GGL_LINEAR;
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params)
+{
+   CALL_GL_API(glTexParameteriv, target, pname, params);
+}
+void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glTexSubImage2D target=0x%.4X level=%d xoffset=%d yoffset=%d width=%d height=%d format=0x%.4X type=0x%.4X pixels=%p",
+//        target, level, xoffset, yoffset, width, height, format, type, pixels);
+   assert(0 == level);
+   assert(target == ctx->tex.tmus[ctx->tex.active]->type);
+   switch (type) {
+   case GL_UNSIGNED_BYTE:
+      break;
+   case GL_UNSIGNED_SHORT_5_6_5:
+      format = GL_UNSIGNED_SHORT_5_6_5;
+      assert(4 == ctx->tex.unpack);
+      break;
+   default:
+      assert(0);
+   }
+   GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
+   GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
+   unsigned bytesPerPixel = 0;
+   GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat);
+   assert(texFormat == tex.format);
+   assert(GL_UNSIGNED_BYTE == type);
+   switch (target) {
+   case GL_TEXTURE_2D:
+      CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, xoffset,
+                  yoffset, tex.width, width, height);
+      break;
+   default:
+      assert(0);
+   }
+   ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
+}
diff --git a/opengl/libagl2/src/vertex.cpp b/opengl/libagl2/src/vertex.cpp
new file mode 100644
index 0000000..021b82b
--- /dev/null
+++ b/opengl/libagl2/src/vertex.cpp
@@ -0,0 +1,373 @@
+#include "gles2context.h"
+
+//#undef LOGD
+//#define LOGD(...)
+
+void GLES2Context::InitializeVertices()
+{
+   vert.vbos = std::map<GLuint, VBO *>(); // the entire struct has been zeroed in constructor
+   vert.free = 1;
+   vert.vbo = NULL;
+   vert.indices = NULL;
+   for (unsigned i = 0; i < GGL_MAXVERTEXATTRIBS; i++)
+      vert.defaultAttribs[i] = Vector4(0,0,0,1);
+}
+
+void GLES2Context::UninitializeVertices()
+{
+   for (std::map<GLuint, VBO *>::iterator it = vert.vbos.begin(); it != vert.vbos.end(); it++) {
+      if (!it->second)
+         continue;
+      free(it->second->data);
+      free(it->second);
+   }
+}
+
+static inline void FetchElement(const GLES2Context * ctx, const unsigned index,
+                                const unsigned maxAttrib, VertexInput * elem)
+{
+   for (unsigned i = 0; i < maxAttrib; i++) {
+      {
+         unsigned size = 0;
+         if (ctx->vert.attribs[i].enabled) {
+            const char * ptr = (const char *)ctx->vert.attribs[i].ptr;
+            ptr += ctx->vert.attribs[i].stride * index;
+            memcpy(elem->attributes + i, ptr, ctx->vert.attribs[i].size * sizeof(float));
+            size = ctx->vert.attribs[i].size;
+//            LOGD("agl2: FetchElement %d attribs size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
+//                 elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
+         } else {
+//            LOGD("agl2: FetchElement %d default %.2f,%.2f,%.2f,%.2f", i, ctx->vert.defaultAttribs[i].x,
+//                 ctx->vert.defaultAttribs[i].y, ctx->vert.defaultAttribs[i].z, ctx->vert.defaultAttribs[i].w);
+         }
+
+         switch (size) {
+         case 0: // fall through
+            elem->attributes[i].x = ctx->vert.defaultAttribs[i].x;
+         case 1: // fall through
+            elem->attributes[i].y = ctx->vert.defaultAttribs[i].y;
+         case 2: // fall through
+            elem->attributes[i].z = ctx->vert.defaultAttribs[i].z;
+         case 3: // fall through
+            elem->attributes[i].w = ctx->vert.defaultAttribs[i].w;
+         case 4:
+            break;
+         default:
+            assert(0);
+            break;
+         }
+//         LOGD("agl2: FetchElement %d size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
+//              elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
+      }
+   }
+}
+
+template<typename IndexT> static void DrawElementsTriangles(const GLES2Context * ctx,
+      const unsigned count, const IndexT * indices, const unsigned maxAttrib)
+{
+   VertexInput v[3];
+   if (ctx->vert.indices)
+      indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
+   for (unsigned i = 0; i < count; i += 3) {
+      for (unsigned j = 0; j < 3; j++)
+         FetchElement(ctx, indices[i + j], maxAttrib, v + j);
+      ctx->iface->DrawTriangle(ctx->iface, v, v + 1, v + 2);
+   }
+}
+
+static void DrawArraysTriangles(const GLES2Context * ctx, const unsigned first,
+                                const unsigned count, const unsigned maxAttrib)
+{
+//   LOGD("agl: DrawArraysTriangles=%p", DrawArraysTriangles);
+   VertexInput v[3];
+   for (unsigned i = 2; i < count; i+=3) {
+      // TODO: fix order
+      FetchElement(ctx, first + i - 2, maxAttrib, v + 0);
+      FetchElement(ctx, first + i - 1, maxAttrib, v + 1);
+      FetchElement(ctx, first + i - 0, maxAttrib, v + 2);
+      ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
+   }
+//   LOGD("agl: DrawArraysTriangles end");
+}
+
+template<typename IndexT> static void DrawElementsTriangleStrip(const GLES2Context * ctx,
+      const unsigned count, const IndexT * indices, const unsigned maxAttrib)
+{
+   VertexInput v[3];
+   if (ctx->vert.indices)
+      indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
+      
+//   LOGD("agl2: DrawElementsTriangleStrip");
+//   for (unsigned i = 0; i < count; i++)
+//      LOGD("indices[%d] = %d", i, indices[i]);
+
+   FetchElement(ctx, indices[0], maxAttrib, v + 0);
+   FetchElement(ctx, indices[1], maxAttrib, v + 1);
+   for (unsigned i = 2; i < count; i ++) {
+      FetchElement(ctx, indices[i], maxAttrib, v + i % 3);
+      ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
+   }
+
+//   for (unsigned i = 2; i < count; i++) {
+//      FetchElement(ctx, indices[i - 2], maxAttrib, v + 0);
+//      FetchElement(ctx, indices[i - 1], maxAttrib, v + 1);
+//      FetchElement(ctx, indices[i - 0], maxAttrib, v + 2);
+//      ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
+//   }
+}
+
+static void DrawArraysTriangleStrip(const GLES2Context * ctx, const unsigned first,
+                                    const unsigned count, const unsigned maxAttrib)
+{
+   VertexInput v[3];
+   FetchElement(ctx, first, maxAttrib, v + 0);
+   FetchElement(ctx, first + 1, maxAttrib, v + 1);
+   for (unsigned i = 2; i < count; i++) {
+      // TODO: fix order
+      FetchElement(ctx, first + i, maxAttrib, v + i % 3);
+      ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
+   }
+}
+
+void glBindBuffer(GLenum target, GLuint buffer)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   VBO * vbo = NULL;
+   if (0 != buffer) {
+      std::map<GLuint, VBO *>::iterator it = ctx->vert.vbos.find(buffer);
+      if (it != ctx->vert.vbos.end()) {
+         vbo = it->second;
+         if (!vbo)
+            vbo = (VBO *)calloc(1, sizeof(VBO));
+         it->second = vbo;
+      } else
+         assert(0);
+   }
+   if (GL_ARRAY_BUFFER == target)
+      ctx->vert.vbo = vbo;
+   else if (GL_ELEMENT_ARRAY_BUFFER == target)
+      ctx->vert.indices = vbo;
+   else
+      assert(0);
+   assert(vbo || buffer == 0);
+//   LOGD("\n*\n glBindBuffer 0x%.4X=%d ", target, buffer);
+}
+
+void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   if (GL_ARRAY_BUFFER == target) {
+      assert(ctx->vert.vbo);
+      ctx->vert.vbo->data = realloc(ctx->vert.vbo->data, size);
+      ctx->vert.vbo->size = size;
+      ctx->vert.vbo->usage = usage;
+      if (data)
+         memcpy(ctx->vert.vbo->data, data, size);
+   } else if (GL_ELEMENT_ARRAY_BUFFER == target) {
+      assert(ctx->vert.indices);
+      ctx->vert.indices->data = realloc(ctx->vert.indices->data, size);
+      ctx->vert.indices->size = size;
+      ctx->vert.indices->usage = usage;
+      if (data)
+         memcpy(ctx->vert.indices->data, data, size);
+   } else
+      assert(0);
+//   LOGD("\n*\n glBufferData target=0x%.4X size=%u data=%p usage=0x%.4X \n",
+//        target, size, data, usage);
+}
+
+void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   if (GL_ARRAY_BUFFER == target)
+   {
+      assert(ctx->vert.vbo);
+      assert(0 <= offset);
+      assert(0 <= size);
+      assert(offset + size <= ctx->vert.vbo->size);
+      memcpy((char *)ctx->vert.vbo->data + offset, data, size);
+   }
+   else
+      assert(0);
+}
+
+void glDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      std::map<GLuint, VBO*>::iterator it = ctx->vert.vbos.find(buffers[i]);
+      if (it == ctx->vert.vbos.end())
+         continue;
+      ctx->vert.free = min(ctx->vert.free, buffers[i]);
+      if (it->second == ctx->vert.vbo)
+         ctx->vert.vbo = NULL;
+      else if (it->second == ctx->vert.indices)
+         ctx->vert.indices = NULL;
+      if (it->second) {
+         free(it->second->data);
+         free(it->second);
+      }
+   }
+}
+
+void glDisableVertexAttribArray(GLuint index)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   assert(GGL_MAXVERTEXATTRIBS > index);
+   ctx->vert.attribs[index].enabled = false;
+}
+
+void glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glDrawArrays=%p", glDrawArrays);
+   assert(ctx->rasterizer.CurrentProgram);
+   assert(0 <= first);
+   int maxAttrib = -1;
+   ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
+   assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
+   switch (mode) {
+   case GL_TRIANGLE_STRIP:
+      DrawArraysTriangleStrip(ctx, first, count, maxAttrib);
+      break;
+   case GL_TRIANGLES:
+      DrawArraysTriangles(ctx, first, count, maxAttrib);
+      break;
+   default:
+      LOGE("agl2: glDrawArrays unsupported mode: 0x%.4X \n", mode);
+      assert(0);
+      break;
+   }
+//   LOGD("agl2: glDrawArrays end");
+}
+
+void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("agl2: glDrawElements=%p mode=0x%.4X count=%d type=0x%.4X indices=%p",
+//        glDrawElements, mode, count, type, indices);
+   if (!ctx->rasterizer.CurrentProgram)
+      return;
+
+   int maxAttrib = -1;
+   ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
+   assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
+//   LOGD("agl2: glDrawElements mode=0x%.4X type=0x%.4X count=%d program=%p indices=%p \n",
+//        mode, type, count, ctx->rasterizer.CurrentProgram, indices);
+   switch (mode) {
+   case GL_TRIANGLES:
+      if (GL_UNSIGNED_SHORT == type)
+         DrawElementsTriangles<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
+      else
+         assert(0);
+      break;
+   case GL_TRIANGLE_STRIP:
+      if (GL_UNSIGNED_SHORT == type)
+         DrawElementsTriangleStrip<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
+      else
+         assert(0);
+      break;
+   default:
+      assert(0);
+   }
+//   LOGD("agl2: glDrawElements end");
+}
+
+void glEnableVertexAttribArray(GLuint index)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   ctx->vert.attribs[index].enabled = true;
+//   LOGD("agl2: glEnableVertexAttribArray %d \n", index);
+}
+
+void glGenBuffers(GLsizei n, GLuint* buffers)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   for (unsigned i = 0; i < n; i++) {
+      buffers[i] = 0;
+      for (ctx->vert.free; ctx->vert.free < 0xffffffffu; ctx->vert.free++) {
+         if (ctx->vert.vbos.find(ctx->vert.free) == ctx->vert.vbos.end()) {
+            ctx->vert.vbos[ctx->vert.free] = NULL;
+            buffers[i] = ctx->vert.free;
+//            LOGD("glGenBuffers %d \n", buffers[i]);
+            ctx->vert.free++;
+            break;
+         }
+      }
+      assert(buffers[i]);
+   }
+}
+
+void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized,
+                           GLsizei stride, const GLvoid* ptr)
+{
+   GLES2_GET_CONST_CONTEXT(ctx);
+   assert(GL_FLOAT == type);
+   assert(0 < size && 4 >= size);
+   ctx->vert.attribs[index].size = size;
+   ctx->vert.attribs[index].type = type;
+   ctx->vert.attribs[index].normalized = normalized;
+   if (0 == stride)
+      ctx->vert.attribs[index].stride = size * sizeof(float);
+   else if (stride > 0)
+      ctx->vert.attribs[index].stride = stride;
+   else
+      assert(0);
+//   LOGD("\n*\n*\n* agl2: glVertexAttribPointer program=%u index=%d size=%d stride=%d ptr=%p \n*\n*",
+//        unsigned(ctx->rasterizer.CurrentProgram) ^ 0x04dc18f9, index, size, stride, ptr);
+   if (ctx->vert.vbo)
+      ctx->vert.attribs[index].ptr = (char *)ctx->vert.vbo->data + (long)ptr;
+   else
+      ctx->vert.attribs[index].ptr = ptr;
+//   const float * attrib = (const float *)ctx->vert.attribs[index].ptr;
+//   for (unsigned i = 0; i < 3; i++)
+//      if (3 == size)
+//         LOGD("%.2f %.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1], attrib[i * 3 + 2]);
+//      else if (2 == size)
+//         LOGD("%.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1]);
+   
+}
+
+void glVertexAttrib1f(GLuint indx, GLfloat x)
+{
+   glVertexAttrib4f(indx, x,0,0,1);
+}
+
+void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0],0,0,1);
+}
+
+void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+   glVertexAttrib4f(indx, x,y,0,1);
+}
+
+void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0],values[1],0,1);
+}
+
+void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+   glVertexAttrib4f(indx, x,y,z,1);
+}
+
+void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0],values[1],values[2],1);
+}
+
+void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+   assert(GGL_MAXVERTEXATTRIBS > indx);
+   GLES2_GET_CONST_CONTEXT(ctx);
+//   LOGD("\n*\n*\n agl2: glVertexAttrib4f %d %.2f,%.2f,%.2f,%.2f \n*\n*", indx, x, y, z, w);
+   ctx->vert.defaultAttribs[indx] = Vector4(x,y,z,w);
+   assert(0);
+}
+
+void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+   glVertexAttrib4f(indx, values[0], values[1], values[2], values[3]);
+}
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index c8041fc..123306b6 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -13,11 +13,11 @@
 	EGL/hooks.cpp 	       \
 	EGL/Loader.cpp 	       \
 #
-
-LOCAL_SHARED_LIBRARIES += libcutils libutils
+LOCAL_STATIC_LIBRARIES += libGLESv2_dbg libprotobuf-cpp-2.3.0-lite
+LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libEGL
-
+LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
 # needed on sim build because of weird logging issues
 ifeq ($(TARGET_SIMULATOR),true)
 else
@@ -164,3 +164,6 @@
 LOCAL_MODULE:= libETC1
 
 include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 747c829..2502f15 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -30,6 +30,7 @@
 #include "egl_impl.h"
 
 #include "Loader.h"
+#include "glesv2dbg.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
@@ -114,6 +115,7 @@
 
 Loader::~Loader()
 {
+    StopDebugServer();
 }
 
 const char* Loader::getTag(int dpy, int impl)
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 3d5a4d1..861d7ac 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -45,6 +45,7 @@
 #include "hooks.h"
 #include "egl_impl.h"
 #include "Loader.h"
+#include "glesv2dbg.h"
 
 #define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
 
@@ -223,9 +224,15 @@
     egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
             int impl, egl_connection_t const* cnx, int version) 
     : dpy(dpy), context(context), config(config), read(0), draw(0), impl(impl),
-      cnx(cnx), version(version)
+      cnx(cnx), version(version), dbg(NULL)
     {
     }
+    ~egl_context_t()
+    {
+        if (dbg)
+            DestroyDbgContext(dbg);
+        dbg = NULL;
+    }
     EGLDisplay                  dpy;
     EGLContext                  context;
     EGLConfig                   config;
@@ -234,6 +241,7 @@
     int                         impl;
     egl_connection_t const*     cnx;
     int                         version;
+    DbgContext *                dbg;
 };
 
 struct egl_image_t : public egl_object_t
@@ -296,9 +304,9 @@
 
 // ----------------------------------------------------------------------------
 
-static int gEGLTraceLevel;
+static int gEGLTraceLevel, gEGLDebugLevel;
 static int gEGLApplicationTraceLevel;
-extern EGLAPI gl_hooks_t gHooksTrace;
+extern EGLAPI gl_hooks_t gHooksTrace, gHooksDebug;
 
 static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
     pthread_setspecific(gGLTraceKey, value);
@@ -314,12 +322,35 @@
     int propertyLevel = atoi(value);
     int applicationLevel = gEGLApplicationTraceLevel;
     gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
+    
+    property_get("debug.egl.debug_proc", value, "");
+    long pid = getpid();
+    char procPath[128] = {};
+    sprintf(procPath, "/proc/%ld/cmdline", pid);
+    FILE * file = fopen(procPath, "r");
+    if (file)
+    {
+        char cmdline[256] = {};
+        if (fgets(cmdline, sizeof(cmdline) - 1, file))
+        {
+            if (!strcmp(value, cmdline))
+                gEGLDebugLevel = 1;
+        }    
+        fclose(file);
+    }
+    
+    if (gEGLDebugLevel > 0)
+        StartDebugServer();
 }
 
 static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
     if (gEGLTraceLevel > 0) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksTrace);
+    } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
+        setGlTraceThreadSpecific(value);
+        setGlThreadSpecific(&gHooksDebug);
+        LOGD("\n* setGLHooksThreadSpecific gHooksDebug");
     } else {
         setGlThreadSpecific(value);
     }
@@ -561,6 +592,11 @@
     return egl_to_native_cast<egl_context_t>(context);
 }
 
+DbgContext * getDbgContextThreadSpecific()
+{
+    return get_context(getContext())->dbg;
+}
+
 static inline
 egl_image_t* get_image(EGLImageKHR image) {
     return egl_to_native_cast<egl_image_t>(image);
@@ -1368,6 +1404,8 @@
         loseCurrent(cur_c);
 
         if (ctx != EGL_NO_CONTEXT) {
+            if (!c->dbg && gEGLDebugLevel > 0)
+                c->dbg = CreateDbgContext(c->version, c->cnx->hooks[c->version]);
             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
@@ -1597,7 +1635,7 @@
                     cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
                     cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
 #if EGL_TRACE
-                    gHooksTrace.ext.extensions[slot] =
+                    gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
 #endif
                             cnx->egl.eglGetProcAddress(procname);
                 }
@@ -1625,6 +1663,10 @@
 
 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
 {
+    EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw);
+    if (gEGLDebugLevel > 0)
+        Debug_eglSwapBuffers(dpy, draw);
+
     clearError();
 
     SurfaceRef _s(draw);
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
index d3e96ba..f3e101b 100644
--- a/opengl/libs/EGL/trace.cpp
+++ b/opengl/libs/EGL/trace.cpp
@@ -325,7 +325,7 @@
 
 #define TRACE_GL(_type, _api, _args, _argList, ...)                       \
 static _type Tracing_ ## _api _args {                                     \
-    TraceGL(#_api, __VA_ARGS__);                                          \
+    TraceGL(#_api, __VA_ARGS__);                                        \
     gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
     return _c->_api _argList;                                             \
 }
@@ -333,11 +333,11 @@
 extern "C" {
 #include "../trace.in"
 }
+
 #undef TRACE_GL_VOID
 #undef TRACE_GL
 
 #define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
-
 EGLAPI gl_hooks_t gHooksTrace = {
     {
         #include "entries.in"
@@ -348,6 +348,48 @@
 };
 #undef GL_ENTRY
 
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+// define the ES 1.0 Debug_gl* functions as Tracing_gl functions
+#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
+static void Debug_ ## _api _args {                                      \
+    TraceGL(#_api, __VA_ARGS__);                                          \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    _c->_api _argList;                                                    \
+}
+
+#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
+static _type Debug_ ## _api _args {                                     \
+    TraceGL(#_api, __VA_ARGS__);                                        \
+    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
+    return _c->_api _argList;                                             \
+}
+
+extern "C" {
+#include "../debug.in"
+}
+
+#undef TRACE_GL_VOID
+#undef TRACE_GL
+
+// declare all Debug_gl* functions
+#define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
+#include "glesv2dbg_functions.h"
+#undef GL_ENTRY
+
+#define GL_ENTRY(_r, _api, ...) Debug_ ## _api,
+EGLAPI gl_hooks_t gHooksDebug = {
+    {
+        #include "entries.in"
+    },
+    {
+        {0}
+    }
+};
+#undef GL_ENTRY
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/GLES2_dbg/Android.mk b/opengl/libs/GLES2_dbg/Android.mk
new file mode 100644
index 0000000..e593c32
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/Android.mk
@@ -0,0 +1,45 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    src/api.cpp \
+    src/dbgcontext.cpp \
+    src/debugger_message.pb.cpp \
+    src/egl.cpp \
+    src/server.cpp \
+    src/texture.cpp \
+    src/vertex.cpp
+
+LOCAL_C_INCLUDES :=	\
+    $(LOCAL_PATH) \
+    $(LOCAL_PATH)/../ \
+    external/stlport/stlport \
+    external/protobuf/src \
+    bionic
+
+#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
+LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI
+
+ifeq ($(TARGET_ARCH),arm)
+	LOCAL_CFLAGS += -fstrict-aliasing
+endif
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+    # we need to access the private Bionic header <bionic_tls.h>
+    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+    # behavior from the bionic Android.mk file
+    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+    endif
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_MODULE:= libGLESv2_dbg
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/libs/GLES2_dbg/generate_api_cpp.py b/opengl/libs/GLES2_dbg/generate_api_cpp.py
new file mode 100755
index 0000000..5b024ad
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_api_cpp.py
@@ -0,0 +1,207 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# 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.
+#
+
+import os
+import sys
+
+def RemoveAnnotation(line):
+    if line.find(":") >= 0:
+        annotation = line[line.find(":"): line.find(" ", line.find(":"))]
+        return line.replace(annotation, "*")
+    else:
+        return line
+    
+def generate_api(lines):
+    externs = []
+    i = 0
+    # these have been hand written
+    skipFunctions = ["glTexImage2D", "glTexSubImage2D", "glReadPixels",
+"glDrawArrays", "glDrawElements"]
+    
+    # these have an EXTEND_Debug_* macro for getting data
+    extendFunctions = ["glCopyTexImage2D", "glCopyTexSubImage2D", "glShaderSource"]
+    
+    # these also needs to be forwarded to DbgContext
+    contextFunctions = ["glUseProgram", "glEnableVertexAttribArray", "glDisableVertexAttribArray", 
+"glVertexAttribPointer", "glBindBuffer", "glBufferData", "glBufferSubData", "glDeleteBuffers",]
+    
+    for line in lines:
+        if line.find("API_ENTRY(") >= 0: # a function prototype
+            returnType = line[0: line.find(" API_ENTRY(")]
+            functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
+            parameterList = line[line.find(")(") + 2: line.find(") {")]
+            
+            #if line.find("*") >= 0:
+            #    extern = "%s Debug_%s(%s);" % (returnType, functionName, parameterList)
+            #    externs.append(extern)
+            #    continue
+            
+            if functionName in skipFunctions:
+                sys.stderr.write("!\n! skipping function '%s'\n!\n" % (functionName))
+                continue
+                
+            parameters = parameterList.split(',')
+            paramIndex = 0
+            if line.find("*") >= 0 and (line.find("*") < line.find(":") or line.find("*") > line.rfind(":")): # unannotated pointer
+                if not functionName in extendFunctions:
+                    # add function to list of functions that should be hand written, but generate code anyways
+                    extern = "%s Debug_%s(%s);" % (returnType, functionName, RemoveAnnotation(parameterList))
+                    sys.stderr.write("%s should be hand written\n" % (extern))
+                    print "// FIXME: this function has pointers, it should be hand written"
+                    externs.append(extern)
+                
+            print "%s Debug_%s(%s)\n{" % (returnType, functionName, RemoveAnnotation(parameterList))
+            print """    glesv2debugger::Message msg;
+    const bool expectResponse = false;"""
+    
+            if parameterList == "void":
+                parameters = []
+            arguments = ""
+            paramNames = []
+            inout = ""
+            getData = ""
+            
+            callerMembers = ""
+            setCallerMembers = ""
+            setMsgParameters = ""
+            
+            for parameter in parameters:
+                const = parameter.find("const")
+                parameter = parameter.replace("const", "")
+                parameter = parameter.strip()
+                paramType = parameter.split(' ')[0]
+                paramName = parameter.split(' ')[1]
+                annotation = ""
+                arguments += paramName
+                if parameter.find(":") >= 0: # has annotation
+                    assert inout == "" # only one parameter should be annotated
+                    sys.stderr.write("%s is annotated: %s \n" % (functionName, paramType))
+                    inout = paramType.split(":")[2]
+                    annotation = paramType.split(":")[1]
+                    paramType = paramType.split(":")[0]
+                    count = 1
+                    countArg = ""
+                    if annotation.find("*") >= 0: # [1,n] * param
+                        count = int(annotation.split("*")[0])
+                        countArg = annotation.split("*")[1]
+                        assert countArg in paramNames
+                    elif annotation in paramNames:
+                        count = 1
+                        countArg = annotation
+                    elif annotation == "GLstring":
+                        annotation = "strlen(%s)" % (paramName)
+                    else:
+                        count = int(annotation)
+            
+                    setMsgParameters += "    msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName)
+                    if paramType.find("void") >= 0:
+                        getData += "    msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(char));" % (paramName, annotation)
+                    else:
+                        getData += "    msg.mutable_data()->assign(reinterpret_cast<const char *>(%s), %s * sizeof(%s));" % (paramName, annotation, paramType)
+                    paramType += "*"
+                else:     
+                    if paramType == "GLfloat" or paramType == "GLclampf" or paramType.find("*") >= 0:
+                        setMsgParameters += "    msg.set_arg%d(ToInt(%s));\n" % (paramIndex, paramName)
+                    else: 
+                        setMsgParameters += "    msg.set_arg%d(%s);\n" % (paramIndex, paramName)
+                if paramIndex < len(parameters) - 1:
+                        arguments += ', '
+                if const >= 0:
+                    paramType = "const " + paramType
+                paramNames.append(paramName)
+                paramIndex += 1
+                callerMembers += "        %s %s;\n" % (paramType, paramName)
+                setCallerMembers += "    caller.%s = %s;\n" % (paramName, paramName)
+            
+            print "    struct : public FunctionCall {"
+            print callerMembers
+            print "        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {"
+            if inout in ["out", "inout"]: # get timing excluding output data copy
+                print "            nsecs_t c0 = systemTime(timeMode);"
+            if returnType == "void":
+                print "            _c->%s(%s);" % (functionName, arguments)
+            else:
+                print "            const int * ret = reinterpret_cast<const int *>(_c->%s(%s));" % (functionName, arguments)
+                print "            msg.set_ret(ToInt(ret));"
+            if inout in ["out", "inout"]:
+                print "            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);"
+                print "        " + getData
+            if functionName in contextFunctions:
+                print "            getDbgContextThreadSpecific()->%s(%s);" % (functionName, arguments)
+            if returnType == "void":
+                print "            return 0;"
+            else:
+                print "            return ret;"
+            print """        }
+    } caller;"""
+            print setCallerMembers
+            print setMsgParameters
+    
+            if line.find("*") >= 0 or line.find(":") >= 0:
+                print "    // FIXME: check for pointer usage"
+            if inout in ["in", "inout"]:
+                print getData
+            if functionName in extendFunctions:
+                print "    EXTEND_Debug_%s;" % (functionName) 
+            print "    int * ret = MessageLoop(caller, msg, expectResponse,"
+            print "                            glesv2debugger::Message_Function_%s);" % (functionName)
+            if returnType != "void":
+                if returnType == "GLboolean":
+                    print "    return static_cast<GLboolean>(reinterpret_cast<int>(ret));"
+                else:
+                    print "    return reinterpret_cast<%s>(ret);" % (returnType)
+            print "}\n"
+                        
+            
+    print "// FIXME: the following functions should be written by hand"
+    for extern in externs:
+        print extern
+
+if __name__ == "__main__":
+    print """\
+/*
+ ** 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.
+ */
+ 
+// auto generated by generate_api_cpp.py
+
+#include "src/header.h"
+#include "src/api.h"
+
+template<typename T> static int ToInt(const T & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (int &)t; }
+template<typename T> static T FromInt(const int & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (T &)t; }
+"""    
+    lines = open("gl2_api_annotated.in").readlines()
+    generate_api(lines)
+    #lines = open("gl2ext_api.in").readlines()
+    #generate_api(lines)
+            
+
diff --git a/opengl/libs/GLES2_dbg/generate_debug_in.py b/opengl/libs/GLES2_dbg/generate_debug_in.py
new file mode 100755
index 0000000..1280c6f
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_debug_in.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# 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.
+#
+
+import os
+import sys
+
+def append_functions(functions, lines):
+	i = 0
+	for line in lines:
+		if line.find("API_ENTRY(") >= 0: # a function prototype
+			returnType = line[0: line.find(" API_ENTRY(")]
+			functionName = line[line.find("(") + 1: line.find(")")] #extract GL function name
+			parameterList = line[line.find(")(") + 2: line.find(") {")]
+			
+			functions.append(functionName)
+			#print functionName
+			continue
+				
+			parameters = parameterList.split(',')
+			paramIndex = 0
+			if line.find("*") >= 0:
+				print "// FIXME: this function has pointers, it should be hand written"
+				externs.append("%s Tracing_%s(%s);" % (returnType, functionName, parameterList))
+			print "%s Tracing_%s(%s)\n{" % (returnType, functionName, parameterList)
+			
+			if parameterList == "void":
+				parameters = []
+			
+			arguments = ""
+			 
+			for parameter in parameters:
+				parameter = parameter.replace("const", "")
+				parameter = parameter.strip()
+				paramType = parameter.split(' ')[0]
+				paramName = parameter.split(' ')[1]
+				
+				paramIndex += 1
+				
+	return functions
+	
+
+
+if __name__ == "__main__":
+	definedFunctions = []
+	lines = open("gl2_api_annotated.in").readlines()
+	definedFunctions = append_functions(definedFunctions, lines)
+	
+	output = open("../debug.in", "w")
+	lines = open("../trace.in").readlines()
+	output.write("// the following functions are not defined in GLESv2_dbg\n")
+	for line in lines:
+		functionName = ""
+		if line.find("TRACE_GL(") >= 0: # a function prototype
+			functionName = line.split(',')[1].strip()
+		elif line.find("TRACE_GL_VOID(") >= 0: # a function prototype
+			functionName = line[line.find("(") + 1: line.find(",")] #extract GL function name
+		else:
+			continue
+		if functionName in definedFunctions:
+			#print functionName
+			continue
+		else:
+			output.write(line)
+	
diff --git a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
new file mode 100755
index 0000000..b14885b
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
@@ -0,0 +1,139 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+#
+# 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.
+#
+
+import os
+
+def generate_egl_entries(output, lines, i):
+    for line in lines:
+        if line.find("EGL_ENTRY(") >= 0:
+            line = line.split(",")[1].strip() #extract EGL function name
+            output.write("        %s = %d;\n" % (line, i))
+            i += 1
+    return i    
+
+
+def generate_gl_entries(output,lines,i):
+    for line in lines:
+        if line.find("API_ENTRY(") >= 0:
+            line = line[line.find("(") + 1: line.find(")")] #extract GL function name
+            output.write("        %s = %d;\n" % (line, i))
+            i += 1
+    return i
+
+
+if __name__ == "__main__":
+    output = open("debugger_message.proto",'w')
+    output.write("""\
+/*
+ * 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.
+ */
+
+// do not edit; auto generated by generate_debugger_message_proto.py
+
+package com.android.glesv2debugger;
+
+option optimize_for = LITE_RUNTIME;
+
+message Message
+{
+    required int32 context_id = 1; // GL context id
+    enum Function
+    {
+""")
+
+    i = 0;
+    
+    lines = open("gl2_api_annotated.in").readlines()
+    i = generate_gl_entries(output, lines, i)
+    output.write("        // end of GL functions\n")
+    
+    #lines = open("gl2ext_api.in").readlines()
+    #i = generate_gl_entries(output, lines, i)
+    #output.write("        // end of GL EXT functions\n")
+    
+    lines = open("../EGL/egl_entries.in").readlines()
+    i = generate_egl_entries(output, lines, i)
+    output.write("        // end of GL EXT functions\n")
+    
+    output.write("        ACK = %d;\n" % (i))
+    i += 1
+    
+    output.write("        NEG = %d;\n" % (i))
+    i += 1
+    
+    output.write("        CONTINUE = %d;\n" % (i))
+    i += 1
+    
+    output.write("        SKIP = %d;\n" % (i))
+    i += 1
+    
+    output.write("        SETPROP = %d;\n" % (i))
+    i += 1
+    
+    output.write("        CAPTURE = %d;\n" % (i))
+    i += 1
+
+    output.write("""    }
+    required Function function = 2 [default = NEG]; // type/function of message
+    enum Type
+    {
+        BeforeCall = 0;
+        AfterCall = 1;
+        Response = 2; // currently used for misc messages
+    }
+    required Type type = 3;
+    required bool expect_response = 4;
+    optional int32 ret = 5; // return value from previous GL call
+    optional int32 arg0 = 6; // args to GL call
+    optional int32 arg1 = 7;
+    optional int32 arg2 = 8;
+    optional int32 arg3 = 9;
+    optional int32 arg4 = 16;
+    optional int32 arg5 = 17;
+    optional int32 arg6 = 18;
+    optional int32 arg7 = 19;
+    optional int32 arg8 = 20;
+    optional bytes data = 10; // variable length data used for GL call
+    optional float time = 11; // duration of previous GL call (ms)
+    enum Prop
+    {
+        Capture = 0; // arg0 = true | false
+        TimeMode = 1; // arg0 = SYSTEM_TIME_* in utils/Timers.h
+    };
+    optional Prop prop = 21; // used with SETPROP, value in arg0
+    optional float clock = 22; // wall clock in seconds
+}
+""")
+
+    output.close()
+    
+    os.system("aprotoc --cpp_out=src --java_out=../../../../../development/tools/glesv2debugger/src debugger_message.proto")
+    os.system('mv -f "src/debugger_message.pb.cc" "src/debugger_message.pb.cpp"')
diff --git a/opengl/libs/GLES2_dbg/gl2_api_annotated.in b/opengl/libs/GLES2_dbg/gl2_api_annotated.in
new file mode 100644
index 0000000..227e2eb
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/gl2_api_annotated.in
@@ -0,0 +1,426 @@
+void API_ENTRY(glActiveTexture)(GLenum texture) {
+    CALL_GL_API(glActiveTexture, texture);
+}
+void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
+    CALL_GL_API(glAttachShader, program, shader);
+}
+void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar:GLstring:in name) {
+    CALL_GL_API(glBindAttribLocation, program, index, name);
+}
+void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
+    CALL_GL_API(glBindBuffer, target, buffer);
+}
+void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer) {
+    CALL_GL_API(glBindFramebuffer, target, framebuffer);
+}
+void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer) {
+    CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
+}
+void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
+    CALL_GL_API(glBindTexture, target, texture);
+}
+void API_ENTRY(glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    CALL_GL_API(glBlendColor, red, green, blue, alpha);
+}
+void API_ENTRY(glBlendEquation)( GLenum mode ) {
+    CALL_GL_API(glBlendEquation, mode);
+}
+void API_ENTRY(glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparate, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
+    CALL_GL_API(glBlendFunc, sfactor, dfactor);
+}
+void API_ENTRY(glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparate, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid:size:in data, GLenum usage) {
+    CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid:size:in data) {
+    CALL_GL_API(glBufferSubData, target, offset, size, data);
+}
+GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {
+    CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
+}
+void API_ENTRY(glClear)(GLbitfield mask) {
+    CALL_GL_API(glClear, mask);
+}
+void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    CALL_GL_API(glClearColor, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthf)(GLclampf depth) {
+    CALL_GL_API(glClearDepthf, depth);
+}
+void API_ENTRY(glClearStencil)(GLint s) {
+    CALL_GL_API(glClearStencil, s);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+    CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glCompileShader)(GLuint shader) {
+    CALL_GL_API(glCompileShader, shader);
+}
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
+    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
+    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+    CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border);
+}
+void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint API_ENTRY(glCreateProgram)(void) {
+    CALL_GL_API_RETURN(glCreateProgram);
+}
+GLuint API_ENTRY(glCreateShader)(GLenum type) {
+    CALL_GL_API_RETURN(glCreateShader, type);
+}
+void API_ENTRY(glCullFace)(GLenum mode) {
+    CALL_GL_API(glCullFace, mode);
+}
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint:n:in buffers) {
+    CALL_GL_API(glDeleteBuffers, n, buffers);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint:n:in framebuffers) {
+    CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteProgram)(GLuint program) {
+    CALL_GL_API(glDeleteProgram, program);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint:n:in renderbuffers) {
+    CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDeleteShader)(GLuint shader) {
+    CALL_GL_API(glDeleteShader, shader);
+}
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint:n:in textures) {
+    CALL_GL_API(glDeleteTextures, n, textures);
+}
+void API_ENTRY(glDepthFunc)(GLenum func) {
+    CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag) {
+    CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangef, zNear, zFar);
+}
+void API_ENTRY(glDetachShader)(GLuint program, GLuint shader) {
+    CALL_GL_API(glDetachShader, program, shader);
+}
+void API_ENTRY(glDisable)(GLenum cap) {
+    CALL_GL_API(glDisable, cap);
+}
+void API_ENTRY(glDisableVertexAttribArray)(GLuint index) {
+    CALL_GL_API(glDisableVertexAttribArray, index);
+}
+void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
+    CALL_GL_API(glDrawArrays, mode, first, count);
+}
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
+    CALL_GL_API(glDrawElements, mode, count, type, indices);
+}
+void API_ENTRY(glEnable)(GLenum cap) {
+    CALL_GL_API(glEnable, cap);
+}
+void API_ENTRY(glEnableVertexAttribArray)(GLuint index) {
+    CALL_GL_API(glEnableVertexAttribArray, index);
+}
+void API_ENTRY(glFinish)(void) {
+    CALL_GL_API(glFinish);
+}
+void API_ENTRY(glFlush)(void) {
+    CALL_GL_API(glFlush);
+}
+void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+    CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
+}
+void API_ENTRY(glFrontFace)(GLenum mode) {
+    CALL_GL_API(glFrontFace, mode);
+}
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint:n:out buffers) {
+    CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenerateMipmap)(GLenum target) {
+    CALL_GL_API(glGenerateMipmap, target);
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint:n:out framebuffers) {
+    CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint:n:out renderbuffers) {
+    CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint:n:out textures) {
+    CALL_GL_API(glGenTextures, n, textures);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar:GLstring:in name) {
+    CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar:GLstring:in name) {
+    CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+    CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
+}
+int API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar:GLstring:in name) {
+    CALL_GL_API_RETURN(glGetAttribLocation, program, name);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params) {
+    CALL_GL_API(glGetBooleanv, pname, params);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+GLenum API_ENTRY(glGetError)(void) {
+    CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetFloatv, pname, params);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
+}
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint* params) {
+    CALL_GL_API(glGetIntegerv, pname, params);
+}
+void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint:1:out params) {
+    CALL_GL_API(glGetProgramiv, program, pname, params);
+}
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar:GLstring:out infolog) {
+    CALL_GL_API(glGetProgramInfoLog, program, bufsize, length, infolog);
+}
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint:1:out params) {
+    CALL_GL_API(glGetShaderiv, shader, pname, params);
+}
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar:GLstring:out infolog) {
+    CALL_GL_API(glGetShaderInfoLog, shader, bufsize, length, infolog);
+}
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+    CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
+}
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar:GLstring:out source) {
+    CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
+}
+const GLubyte* API_ENTRY(glGetString)(GLenum name) {
+    CALL_GL_API_RETURN(glGetString, name);
+}
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params) {
+    CALL_GL_API(glGetUniformfv, program, location, params);
+}
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params) {
+    CALL_GL_API(glGetUniformiv, program, location, params);
+}
+int API_ENTRY(glGetUniformLocation)(GLuint program, const GLchar:GLstring:in name) {
+    CALL_GL_API_RETURN(glGetUniformLocation, program, name);
+}
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetVertexAttribfv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetVertexAttribiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) {
+    CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
+}
+void API_ENTRY(glHint)(GLenum target, GLenum mode) {
+    CALL_GL_API(glHint, target, mode);
+}
+GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
+    CALL_GL_API_RETURN(glIsBuffer, buffer);
+}
+GLboolean API_ENTRY(glIsEnabled)(GLenum cap) {
+    CALL_GL_API_RETURN(glIsEnabled, cap);
+}
+GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer) {
+    CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
+}
+GLboolean API_ENTRY(glIsProgram)(GLuint program) {
+    CALL_GL_API_RETURN(glIsProgram, program);
+}
+GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer) {
+    CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
+}
+GLboolean API_ENTRY(glIsShader)(GLuint shader) {
+    CALL_GL_API_RETURN(glIsShader, shader);
+}
+GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
+    CALL_GL_API_RETURN(glIsTexture, texture);
+}
+void API_ENTRY(glLineWidth)(GLfloat width) {
+    CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glLinkProgram)(GLuint program) {
+    CALL_GL_API(glLinkProgram, program);
+}
+void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
+    CALL_GL_API(glPixelStorei, pname, param);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
+    CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
+    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glReleaseShaderCompiler)(void) {
+    CALL_GL_API(glReleaseShaderCompiler);
+}
+void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+    CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
+    CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glScissor, x, y, width, height);
+}
+void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) {
+    CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) {
+    CALL_GL_API(glShaderSource, shader, count, string, length);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask) {
+    CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask) {
+    CALL_GL_API(glStencilMaskSeparate, face, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
+}
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) {
+    CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
+}
+void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexParameterf, target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) {
+    CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
+    CALL_GL_API(glTexParameteri, target, pname, param);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) {
+    CALL_GL_API(glTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) {
+    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void API_ENTRY(glUniform1f)(GLint location, GLfloat x) {
+    CALL_GL_API(glUniform1f, location, x);
+}
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat:1*count:in v) {
+    CALL_GL_API(glUniform1fv, location, count, v);
+}
+void API_ENTRY(glUniform1i)(GLint location, GLint x) {
+    CALL_GL_API(glUniform1i, location, x);
+}
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint:1*count:in v) {
+    CALL_GL_API(glUniform1iv, location, count, v);
+}
+void API_ENTRY(glUniform2f)(GLint location, GLfloat x, GLfloat y) {
+    CALL_GL_API(glUniform2f, location, x, y);
+}
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat:2*count:in v) {
+    CALL_GL_API(glUniform2fv, location, count, v);
+}
+void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y) {
+    CALL_GL_API(glUniform2i, location, x, y);
+}
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint:2*count:in v) {
+    CALL_GL_API(glUniform2iv, location, count, v);
+}
+void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glUniform3f, location, x, y, z);
+}
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat:3*count:in v) {
+    CALL_GL_API(glUniform3fv, location, count, v);
+}
+void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z) {
+    CALL_GL_API(glUniform3i, location, x, y, z);
+}
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint:3*count:in v) {
+    CALL_GL_API(glUniform3iv, location, count, v);
+}
+void API_ENTRY(glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    CALL_GL_API(glUniform4f, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat:4*count:in v) {
+    CALL_GL_API(glUniform4fv, location, count, v);
+}
+void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) {
+    CALL_GL_API(glUniform4i, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint:4*count:in v) {
+    CALL_GL_API(glUniform4iv, location, count, v);
+}
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat:4*count:in value) {
+    CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat:9*count:in value) {
+    CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat:16*count:in value) {
+    CALL_GL_API(glUniformMatrix4fv, location, count, transpose, value);
+}
+void API_ENTRY(glUseProgram)(GLuint program) {
+    CALL_GL_API(glUseProgram, program);
+}
+void API_ENTRY(glValidateProgram)(GLuint program) {
+    CALL_GL_API(glValidateProgram, program);
+}
+void API_ENTRY(glVertexAttrib1f)(GLuint indx, GLfloat x) {
+    CALL_GL_API(glVertexAttrib1f, indx, x);
+}
+void API_ENTRY(glVertexAttrib1fv)(GLuint indx, const GLfloat:1:in values) {
+    CALL_GL_API(glVertexAttrib1fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) {
+    CALL_GL_API(glVertexAttrib2f, indx, x, y);
+}
+void API_ENTRY(glVertexAttrib2fv)(GLuint indx, const GLfloat:2:in values) {
+    CALL_GL_API(glVertexAttrib2fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glVertexAttrib3f, indx, x, y, z);
+}
+void API_ENTRY(glVertexAttrib3fv)(GLuint indx, const GLfloat:3:in values) {
+    CALL_GL_API(glVertexAttrib3fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    CALL_GL_API(glVertexAttrib4f, indx, x, y, z, w);
+}
+void API_ENTRY(glVertexAttrib4fv)(GLuint indx, const GLfloat:4:in values) {
+    CALL_GL_API(glVertexAttrib4fv, indx, values);
+}
+void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) {
+    CALL_GL_API(glVertexAttribPointer, indx, size, type, normalized, stride, ptr);
+}
+void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glViewport, x, y, width, height);
+}
diff --git a/opengl/libs/GLES2_dbg/src/api.cpp b/opengl/libs/GLES2_dbg/src/api.cpp
new file mode 100644
index 0000000..7094ca7
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/api.cpp
@@ -0,0 +1,3653 @@
+/*
+ ** 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.
+ */
+ 
+// auto generated by generate_api_cpp.py
+
+#include "src/header.h"
+#include "src/api.h"
+
+template<typename T> static int ToInt(const T & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (int &)t; }
+template<typename T> static T FromInt(const int & t) { STATIC_ASSERT(sizeof(T) == sizeof(int), bitcast); return (T &)t; }
+
+void Debug_glActiveTexture(GLenum texture)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glActiveTexture(texture);
+            return 0;
+        }
+    } caller;
+    caller.texture = texture;
+
+    msg.set_arg0(texture);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glActiveTexture);
+}
+
+void Debug_glAttachShader(GLuint program, GLuint shader)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glAttachShader(program, shader);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.shader = shader;
+
+    msg.set_arg0(program);
+    msg.set_arg1(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glAttachShader);
+}
+
+void Debug_glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindAttribLocation(program, index, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindAttribLocation);
+}
+
+void Debug_glBindBuffer(GLenum target, GLuint buffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint buffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindBuffer(target, buffer);
+            getDbgContextThreadSpecific()->glBindBuffer(target, buffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.buffer = buffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(buffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindBuffer);
+}
+
+void Debug_glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint framebuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindFramebuffer(target, framebuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.framebuffer = framebuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(framebuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindFramebuffer);
+}
+
+void Debug_glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindRenderbuffer(target, renderbuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindRenderbuffer);
+}
+
+void Debug_glBindTexture(GLenum target, GLuint texture)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLuint texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBindTexture(target, texture);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.texture = texture;
+
+    msg.set_arg0(target);
+    msg.set_arg1(texture);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBindTexture);
+}
+
+void Debug_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf red;
+        GLclampf green;
+        GLclampf blue;
+        GLclampf alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendColor(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(ToInt(red));
+    msg.set_arg1(ToInt(green));
+    msg.set_arg2(ToInt(blue));
+    msg.set_arg3(ToInt(alpha));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendColor);
+}
+
+void Debug_glBlendEquation( GLenum mode )
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendEquation(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendEquation);
+}
+
+void Debug_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum modeRGB;
+        GLenum modeAlpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendEquationSeparate(modeRGB, modeAlpha);
+            return 0;
+        }
+    } caller;
+    caller.modeRGB = modeRGB;
+    caller.modeAlpha = modeAlpha;
+
+    msg.set_arg0(modeRGB);
+    msg.set_arg1(modeAlpha);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendEquationSeparate);
+}
+
+void Debug_glBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum sfactor;
+        GLenum dfactor;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendFunc(sfactor, dfactor);
+            return 0;
+        }
+    } caller;
+    caller.sfactor = sfactor;
+    caller.dfactor = dfactor;
+
+    msg.set_arg0(sfactor);
+    msg.set_arg1(dfactor);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendFunc);
+}
+
+void Debug_glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum srcRGB;
+        GLenum dstRGB;
+        GLenum srcAlpha;
+        GLenum dstAlpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+            return 0;
+        }
+    } caller;
+    caller.srcRGB = srcRGB;
+    caller.dstRGB = dstRGB;
+    caller.srcAlpha = srcAlpha;
+    caller.dstAlpha = dstAlpha;
+
+    msg.set_arg0(srcRGB);
+    msg.set_arg1(dstRGB);
+    msg.set_arg2(srcAlpha);
+    msg.set_arg3(dstAlpha);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBlendFuncSeparate);
+}
+
+void Debug_glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLsizeiptr size;
+        const GLvoid* data;
+        GLenum usage;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBufferData(target, size, data, usage);
+            getDbgContextThreadSpecific()->glBufferData(target, size, data, usage);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.size = size;
+    caller.data = data;
+    caller.usage = usage;
+
+    msg.set_arg0(target);
+    msg.set_arg1(size);
+    msg.set_arg2(ToInt(data));
+    msg.set_arg3(usage);
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(data), size * sizeof(char));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBufferData);
+}
+
+void Debug_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLintptr offset;
+        GLsizeiptr size;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glBufferSubData(target, offset, size, data);
+            getDbgContextThreadSpecific()->glBufferSubData(target, offset, size, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.offset = offset;
+    caller.size = size;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(offset);
+    msg.set_arg2(size);
+    msg.set_arg3(ToInt(data));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(data), size * sizeof(char));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glBufferSubData);
+}
+
+GLenum Debug_glCheckFramebufferStatus(GLenum target)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCheckFramebufferStatus(target));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.target = target;
+
+    msg.set_arg0(target);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCheckFramebufferStatus);
+    return reinterpret_cast<GLenum>(ret);
+}
+
+void Debug_glClear(GLbitfield mask)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLbitfield mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClear(mask);
+            return 0;
+        }
+    } caller;
+    caller.mask = mask;
+
+    msg.set_arg0(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClear);
+}
+
+void Debug_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf red;
+        GLclampf green;
+        GLclampf blue;
+        GLclampf alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearColor(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(ToInt(red));
+    msg.set_arg1(ToInt(green));
+    msg.set_arg2(ToInt(blue));
+    msg.set_arg3(ToInt(alpha));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClearColor);
+}
+
+void Debug_glClearDepthf(GLclampf depth)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf depth;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearDepthf(depth);
+            return 0;
+        }
+    } caller;
+    caller.depth = depth;
+
+    msg.set_arg0(ToInt(depth));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClearDepthf);
+}
+
+void Debug_glClearStencil(GLint s)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint s;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glClearStencil(s);
+            return 0;
+        }
+    } caller;
+    caller.s = s;
+
+    msg.set_arg0(s);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glClearStencil);
+}
+
+void Debug_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLboolean red;
+        GLboolean green;
+        GLboolean blue;
+        GLboolean alpha;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glColorMask(red, green, blue, alpha);
+            return 0;
+        }
+    } caller;
+    caller.red = red;
+    caller.green = green;
+    caller.blue = blue;
+    caller.alpha = alpha;
+
+    msg.set_arg0(red);
+    msg.set_arg1(green);
+    msg.set_arg2(blue);
+    msg.set_arg3(alpha);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glColorMask);
+}
+
+void Debug_glCompileShader(GLuint shader)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompileShader(shader);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCompileShader);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLenum internalformat;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+        GLsizei imageSize;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+    caller.imageSize = imageSize;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(width);
+    msg.set_arg4(height);
+    msg.set_arg5(border);
+    msg.set_arg6(imageSize);
+    msg.set_arg7(ToInt(data));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCompressedTexImage2D);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLsizei width;
+        GLsizei height;
+        GLenum format;
+        GLsizei imageSize;
+        const GLvoid* data;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.width = width;
+    caller.height = height;
+    caller.format = format;
+    caller.imageSize = imageSize;
+    caller.data = data;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(width);
+    msg.set_arg5(height);
+    msg.set_arg6(format);
+    msg.set_arg7(imageSize);
+    msg.set_arg8(ToInt(data));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCompressedTexSubImage2D);
+}
+
+void Debug_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLenum internalformat;
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(x);
+    msg.set_arg4(y);
+    msg.set_arg5(width);
+    msg.set_arg6(height);
+    msg.set_arg7(border);
+
+    EXTEND_Debug_glCopyTexImage2D;
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCopyTexImage2D);
+}
+
+void Debug_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(x);
+    msg.set_arg5(y);
+    msg.set_arg6(width);
+    msg.set_arg7(height);
+
+    EXTEND_Debug_glCopyTexSubImage2D;
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCopyTexSubImage2D);
+}
+
+GLuint Debug_glCreateProgram(void)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCreateProgram());
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCreateProgram);
+    return reinterpret_cast<GLuint>(ret);
+}
+
+GLuint Debug_glCreateShader(GLenum type)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum type;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glCreateShader(type));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.type = type;
+
+    msg.set_arg0(type);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCreateShader);
+    return reinterpret_cast<GLuint>(ret);
+}
+
+void Debug_glCullFace(GLenum mode)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glCullFace(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glCullFace);
+}
+
+void Debug_glDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* buffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteBuffers(n, buffers);
+            getDbgContextThreadSpecific()->glDeleteBuffers(n, buffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.buffers = buffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(buffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(buffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteBuffers);
+}
+
+void Debug_glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* framebuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteFramebuffers(n, framebuffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.framebuffers = framebuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(framebuffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(framebuffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteFramebuffers);
+}
+
+void Debug_glDeleteProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteProgram);
+}
+
+void Debug_glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* renderbuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteRenderbuffers(n, renderbuffers);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.renderbuffers = renderbuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(renderbuffers));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(renderbuffers), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteRenderbuffers);
+}
+
+void Debug_glDeleteShader(GLuint shader)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteShader(shader);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteShader);
+}
+
+void Debug_glDeleteTextures(GLsizei n, const GLuint* textures)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* textures;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDeleteTextures(n, textures);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.textures = textures;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(textures));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(textures), n * sizeof(GLuint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDeleteTextures);
+}
+
+void Debug_glDepthFunc(GLenum func)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum func;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthFunc(func);
+            return 0;
+        }
+    } caller;
+    caller.func = func;
+
+    msg.set_arg0(func);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDepthFunc);
+}
+
+void Debug_glDepthMask(GLboolean flag)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLboolean flag;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthMask(flag);
+            return 0;
+        }
+    } caller;
+    caller.flag = flag;
+
+    msg.set_arg0(flag);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDepthMask);
+}
+
+void Debug_glDepthRangef(GLclampf zNear, GLclampf zFar)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf zNear;
+        GLclampf zFar;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDepthRangef(zNear, zFar);
+            return 0;
+        }
+    } caller;
+    caller.zNear = zNear;
+    caller.zFar = zFar;
+
+    msg.set_arg0(ToInt(zNear));
+    msg.set_arg1(ToInt(zFar));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDepthRangef);
+}
+
+void Debug_glDetachShader(GLuint program, GLuint shader)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDetachShader(program, shader);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.shader = shader;
+
+    msg.set_arg0(program);
+    msg.set_arg1(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDetachShader);
+}
+
+void Debug_glDisable(GLenum cap)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDisable(cap);
+            return 0;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDisable);
+}
+
+void Debug_glDisableVertexAttribArray(GLuint index)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glDisableVertexAttribArray(index);
+            getDbgContextThreadSpecific()->glDisableVertexAttribArray(index);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+
+    msg.set_arg0(index);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glDisableVertexAttribArray);
+}
+
+void Debug_glEnable(GLenum cap)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glEnable(cap);
+            return 0;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glEnable);
+}
+
+void Debug_glEnableVertexAttribArray(GLuint index)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glEnableVertexAttribArray(index);
+            getDbgContextThreadSpecific()->glEnableVertexAttribArray(index);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+
+    msg.set_arg0(index);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glEnableVertexAttribArray);
+}
+
+void Debug_glFinish(void)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFinish();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFinish);
+}
+
+void Debug_glFlush(void)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFlush();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFlush);
+}
+
+void Debug_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum renderbuffertarget;
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.renderbuffertarget = renderbuffertarget;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(renderbuffertarget);
+    msg.set_arg3(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFramebufferRenderbuffer);
+}
+
+void Debug_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum textarget;
+        GLuint texture;
+        GLint level;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFramebufferTexture2D(target, attachment, textarget, texture, level);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.textarget = textarget;
+    caller.texture = texture;
+    caller.level = level;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(textarget);
+    msg.set_arg3(texture);
+    msg.set_arg4(level);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFramebufferTexture2D);
+}
+
+void Debug_glFrontFace(GLenum mode)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glFrontFace(mode);
+            return 0;
+        }
+    } caller;
+    caller.mode = mode;
+
+    msg.set_arg0(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glFrontFace);
+}
+
+void Debug_glGenBuffers(GLsizei n, GLuint* buffers)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* buffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenBuffers(n, buffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(buffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.buffers = buffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(buffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenBuffers);
+}
+
+void Debug_glGenerateMipmap(GLenum target)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGenerateMipmap(target);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+
+    msg.set_arg0(target);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenerateMipmap);
+}
+
+void Debug_glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* framebuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenFramebuffers(n, framebuffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(framebuffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.framebuffers = framebuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(framebuffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenFramebuffers);
+}
+
+void Debug_glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* renderbuffers;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenRenderbuffers(n, renderbuffers);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(renderbuffers), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.renderbuffers = renderbuffers;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(renderbuffers));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenRenderbuffers);
+}
+
+void Debug_glGenTextures(GLsizei n, GLuint* textures)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        GLuint* textures;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGenTextures(n, textures);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(textures), n * sizeof(GLuint));
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.textures = textures;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(textures));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGenTextures);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLint* size;
+        GLenum* type;
+        GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetActiveAttrib(program, index, bufsize, length, size, type, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.size = size;
+    caller.type = type;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(bufsize);
+    msg.set_arg3(ToInt(length));
+    msg.set_arg4(ToInt(size));
+    msg.set_arg5(ToInt(type));
+    msg.set_arg6(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetActiveAttrib);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLuint index;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLint* size;
+        GLenum* type;
+        GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetActiveUniform(program, index, bufsize, length, size, type, name);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.index = index;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.size = size;
+    caller.type = type;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(index);
+    msg.set_arg2(bufsize);
+    msg.set_arg3(ToInt(length));
+    msg.set_arg4(ToInt(size));
+    msg.set_arg5(ToInt(type));
+    msg.set_arg6(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetActiveUniform);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLsizei maxcount;
+        GLsizei* count;
+        GLuint* shaders;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetAttachedShaders(program, maxcount, count, shaders);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.maxcount = maxcount;
+    caller.count = count;
+    caller.shaders = shaders;
+
+    msg.set_arg0(program);
+    msg.set_arg1(maxcount);
+    msg.set_arg2(ToInt(count));
+    msg.set_arg3(ToInt(shaders));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetAttachedShaders);
+}
+
+int Debug_glGetAttribLocation(GLuint program, const GLchar* name)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetAttribLocation(program, name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetAttribLocation);
+    return reinterpret_cast<int>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetBooleanv(GLenum pname, GLboolean* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLboolean* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetBooleanv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetBooleanv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetBufferParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetBufferParameteriv);
+}
+
+GLenum Debug_glGetError(void)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetError());
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetError);
+    return reinterpret_cast<GLenum>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetFloatv(GLenum pname, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetFloatv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetFloatv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum attachment;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.attachment = attachment;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(attachment);
+    msg.set_arg2(pname);
+    msg.set_arg3(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetFramebufferAttachmentParameteriv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetIntegerv(GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetIntegerv(pname, params);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetIntegerv);
+}
+
+void Debug_glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetProgramiv(program, pname, params);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(params), 1 * sizeof(GLint));
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetProgramiv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* infolog;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetProgramInfoLog(program, bufsize, length, infolog);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(infolog), strlen(infolog) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.infolog = infolog;
+
+    msg.set_arg0(program);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(infolog));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetProgramInfoLog);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetRenderbufferParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetRenderbufferParameteriv);
+}
+
+void Debug_glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderiv(shader, pname, params);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(params), 1 * sizeof(GLint));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderiv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* infolog;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderInfoLog(shader, bufsize, length, infolog);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(infolog), strlen(infolog) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.infolog = infolog;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(infolog));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderInfoLog);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum shadertype;
+        GLenum precisiontype;
+        GLint* range;
+        GLint* precision;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+            return 0;
+        }
+    } caller;
+    caller.shadertype = shadertype;
+    caller.precisiontype = precisiontype;
+    caller.range = range;
+    caller.precision = precision;
+
+    msg.set_arg0(shadertype);
+    msg.set_arg1(precisiontype);
+    msg.set_arg2(ToInt(range));
+    msg.set_arg3(ToInt(precision));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderPrecisionFormat);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei bufsize;
+        GLsizei* length;
+        GLchar* source;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glGetShaderSource(shader, bufsize, length, source);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.mutable_data()->assign(reinterpret_cast<const char *>(source), strlen(source) * sizeof(GLchar));
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.bufsize = bufsize;
+    caller.length = length;
+    caller.source = source;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(bufsize);
+    msg.set_arg2(ToInt(length));
+    msg.set_arg3(ToInt(source));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetShaderSource);
+}
+
+// FIXME: this function has pointers, it should be hand written
+const GLubyte* Debug_glGetString(GLenum name)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetString(name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.name = name;
+
+    msg.set_arg0(name);
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetString);
+    return reinterpret_cast<const GLubyte*>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetTexParameterfv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetTexParameterfv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetTexParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetTexParameteriv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLint location;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetUniformfv(program, location, params);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.location = location;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(location);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetUniformfv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetUniformiv(GLuint program, GLint location, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        GLint location;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetUniformiv(program, location, params);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+    caller.location = location;
+    caller.params = params;
+
+    msg.set_arg0(program);
+    msg.set_arg1(location);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetUniformiv);
+}
+
+int Debug_glGetUniformLocation(GLuint program, const GLchar* name)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+        const GLchar* name;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glGetUniformLocation(program, name));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+    caller.name = name;
+
+    msg.set_arg0(program);
+    msg.set_arg1(ToInt(name));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(name), strlen(name) * sizeof(GLchar));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetUniformLocation);
+    return reinterpret_cast<int>(ret);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribfv(index, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetVertexAttribfv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribiv(index, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetVertexAttribiv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint index;
+        GLenum pname;
+        GLvoid** pointer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glGetVertexAttribPointerv(index, pname, pointer);
+            return 0;
+        }
+    } caller;
+    caller.index = index;
+    caller.pname = pname;
+    caller.pointer = pointer;
+
+    msg.set_arg0(index);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(pointer));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glGetVertexAttribPointerv);
+}
+
+void Debug_glHint(GLenum target, GLenum mode)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum mode;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glHint(target, mode);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.mode = mode;
+
+    msg.set_arg0(target);
+    msg.set_arg1(mode);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glHint);
+}
+
+GLboolean Debug_glIsBuffer(GLuint buffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint buffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsBuffer(buffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.buffer = buffer;
+
+    msg.set_arg0(buffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsBuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsEnabled(GLenum cap)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum cap;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsEnabled(cap));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.cap = cap;
+
+    msg.set_arg0(cap);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsEnabled);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsFramebuffer(GLuint framebuffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint framebuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsFramebuffer(framebuffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.framebuffer = framebuffer;
+
+    msg.set_arg0(framebuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsFramebuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsProgram(program));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsProgram);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsRenderbuffer(GLuint renderbuffer)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint renderbuffer;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsRenderbuffer(renderbuffer));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.renderbuffer = renderbuffer;
+
+    msg.set_arg0(renderbuffer);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsRenderbuffer);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsShader(GLuint shader)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsShader(shader));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.shader = shader;
+
+    msg.set_arg0(shader);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsShader);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+GLboolean Debug_glIsTexture(GLuint texture)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint texture;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            const int * ret = reinterpret_cast<const int *>(_c->glIsTexture(texture));
+            msg.set_ret(ToInt(ret));
+            return ret;
+        }
+    } caller;
+    caller.texture = texture;
+
+    msg.set_arg0(texture);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glIsTexture);
+    return static_cast<GLboolean>(reinterpret_cast<int>(ret));
+}
+
+void Debug_glLineWidth(GLfloat width)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLfloat width;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glLineWidth(width);
+            return 0;
+        }
+    } caller;
+    caller.width = width;
+
+    msg.set_arg0(ToInt(width));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glLineWidth);
+}
+
+void Debug_glLinkProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glLinkProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glLinkProgram);
+}
+
+void Debug_glPixelStorei(GLenum pname, GLint param)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum pname;
+        GLint param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glPixelStorei(pname, param);
+            return 0;
+        }
+    } caller;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(pname);
+    msg.set_arg1(param);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glPixelStorei);
+}
+
+void Debug_glPolygonOffset(GLfloat factor, GLfloat units)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLfloat factor;
+        GLfloat units;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glPolygonOffset(factor, units);
+            return 0;
+        }
+    } caller;
+    caller.factor = factor;
+    caller.units = units;
+
+    msg.set_arg0(ToInt(factor));
+    msg.set_arg1(ToInt(units));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glPolygonOffset);
+}
+
+void Debug_glReleaseShaderCompiler(void)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glReleaseShaderCompiler();
+            return 0;
+        }
+    } caller;
+
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glReleaseShaderCompiler);
+}
+
+void Debug_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum internalformat;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glRenderbufferStorage(target, internalformat, width, height);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(target);
+    msg.set_arg1(internalformat);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glRenderbufferStorage);
+}
+
+void Debug_glSampleCoverage(GLclampf value, GLboolean invert)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLclampf value;
+        GLboolean invert;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glSampleCoverage(value, invert);
+            return 0;
+        }
+    } caller;
+    caller.value = value;
+    caller.invert = invert;
+
+    msg.set_arg0(ToInt(value));
+    msg.set_arg1(invert);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glSampleCoverage);
+}
+
+void Debug_glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glScissor(x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glScissor);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLsizei n;
+        const GLuint* shaders;
+        GLenum binaryformat;
+        const GLvoid* binary;
+        GLsizei length;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glShaderBinary(n, shaders, binaryformat, binary, length);
+            return 0;
+        }
+    } caller;
+    caller.n = n;
+    caller.shaders = shaders;
+    caller.binaryformat = binaryformat;
+    caller.binary = binary;
+    caller.length = length;
+
+    msg.set_arg0(n);
+    msg.set_arg1(ToInt(shaders));
+    msg.set_arg2(binaryformat);
+    msg.set_arg3(ToInt(binary));
+    msg.set_arg4(length);
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glShaderBinary);
+}
+
+void Debug_glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint shader;
+        GLsizei count;
+        const GLchar** string;
+        const GLint* length;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glShaderSource(shader, count, string, length);
+            return 0;
+        }
+    } caller;
+    caller.shader = shader;
+    caller.count = count;
+    caller.string = string;
+    caller.length = length;
+
+    msg.set_arg0(shader);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(string));
+    msg.set_arg3(ToInt(length));
+
+    // FIXME: check for pointer usage
+    EXTEND_Debug_glShaderSource;
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glShaderSource);
+}
+
+void Debug_glStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum func;
+        GLint ref;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilFunc(func, ref, mask);
+            return 0;
+        }
+    } caller;
+    caller.func = func;
+    caller.ref = ref;
+    caller.mask = mask;
+
+    msg.set_arg0(func);
+    msg.set_arg1(ref);
+    msg.set_arg2(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilFunc);
+}
+
+void Debug_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum face;
+        GLenum func;
+        GLint ref;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilFuncSeparate(face, func, ref, mask);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.func = func;
+    caller.ref = ref;
+    caller.mask = mask;
+
+    msg.set_arg0(face);
+    msg.set_arg1(func);
+    msg.set_arg2(ref);
+    msg.set_arg3(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilFuncSeparate);
+}
+
+void Debug_glStencilMask(GLuint mask)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilMask(mask);
+            return 0;
+        }
+    } caller;
+    caller.mask = mask;
+
+    msg.set_arg0(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilMask);
+}
+
+void Debug_glStencilMaskSeparate(GLenum face, GLuint mask)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum face;
+        GLuint mask;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilMaskSeparate(face, mask);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.mask = mask;
+
+    msg.set_arg0(face);
+    msg.set_arg1(mask);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilMaskSeparate);
+}
+
+void Debug_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum fail;
+        GLenum zfail;
+        GLenum zpass;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilOp(fail, zfail, zpass);
+            return 0;
+        }
+    } caller;
+    caller.fail = fail;
+    caller.zfail = zfail;
+    caller.zpass = zpass;
+
+    msg.set_arg0(fail);
+    msg.set_arg1(zfail);
+    msg.set_arg2(zpass);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilOp);
+}
+
+void Debug_glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum face;
+        GLenum fail;
+        GLenum zfail;
+        GLenum zpass;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glStencilOpSeparate(face, fail, zfail, zpass);
+            return 0;
+        }
+    } caller;
+    caller.face = face;
+    caller.fail = fail;
+    caller.zfail = zfail;
+    caller.zpass = zpass;
+
+    msg.set_arg0(face);
+    msg.set_arg1(fail);
+    msg.set_arg2(zfail);
+    msg.set_arg3(zpass);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glStencilOpSeparate);
+}
+
+void Debug_glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLfloat param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameterf(target, pname, param);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(param));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameterf);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        const GLfloat* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameterfv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameterfv);
+}
+
+void Debug_glTexParameteri(GLenum target, GLenum pname, GLint param)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        GLint param;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameteri(target, pname, param);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.param = param;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(param);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameteri);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLenum pname;
+        const GLint* params;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glTexParameteriv(target, pname, params);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.pname = pname;
+    caller.params = params;
+
+    msg.set_arg0(target);
+    msg.set_arg1(pname);
+    msg.set_arg2(ToInt(params));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexParameteriv);
+}
+
+void Debug_glUniform1f(GLint location, GLfloat x)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1f(location, x);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1f);
+}
+
+void Debug_glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 1*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1fv);
+}
+
+void Debug_glUniform1i(GLint location, GLint x)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1i(location, x);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1i);
+}
+
+void Debug_glUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform1iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 1*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform1iv);
+}
+
+void Debug_glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2f(location, x, y);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2f);
+}
+
+void Debug_glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 2*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2fv);
+}
+
+void Debug_glUniform2i(GLint location, GLint x, GLint y)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2i(location, x, y);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2i);
+}
+
+void Debug_glUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform2iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 2*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform2iv);
+}
+
+void Debug_glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3f(location, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3f);
+}
+
+void Debug_glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 3*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3fv);
+}
+
+void Debug_glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+        GLint z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3i(location, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+    msg.set_arg3(z);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3i);
+}
+
+void Debug_glUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform3iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 3*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform3iv);
+}
+
+void Debug_glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+        GLfloat w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4f(location, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(location);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+    msg.set_arg4(ToInt(w));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4f);
+}
+
+void Debug_glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLfloat* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4fv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 4*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4fv);
+}
+
+void Debug_glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLint x;
+        GLint y;
+        GLint z;
+        GLint w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4i(location, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(location);
+    msg.set_arg1(x);
+    msg.set_arg2(y);
+    msg.set_arg3(z);
+    msg.set_arg4(w);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4i);
+}
+
+void Debug_glUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        const GLint* v;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniform4iv(location, count, v);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.v = v;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(ToInt(v));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(v), 4*count * sizeof(GLint));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniform4iv);
+}
+
+void Debug_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix2fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 4*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniformMatrix2fv);
+}
+
+void Debug_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix3fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 9*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniformMatrix3fv);
+}
+
+void Debug_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint location;
+        GLsizei count;
+        GLboolean transpose;
+        const GLfloat* value;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUniformMatrix4fv(location, count, transpose, value);
+            return 0;
+        }
+    } caller;
+    caller.location = location;
+    caller.count = count;
+    caller.transpose = transpose;
+    caller.value = value;
+
+    msg.set_arg0(location);
+    msg.set_arg1(count);
+    msg.set_arg2(transpose);
+    msg.set_arg3(ToInt(value));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(value), 16*count * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUniformMatrix4fv);
+}
+
+void Debug_glUseProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glUseProgram(program);
+            getDbgContextThreadSpecific()->glUseProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glUseProgram);
+}
+
+void Debug_glValidateProgram(GLuint program)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint program;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glValidateProgram(program);
+            return 0;
+        }
+    } caller;
+    caller.program = program;
+
+    msg.set_arg0(program);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glValidateProgram);
+}
+
+void Debug_glVertexAttrib1f(GLuint indx, GLfloat x)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib1f(indx, x);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib1f);
+}
+
+void Debug_glVertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib1fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 1 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib1fv);
+}
+
+void Debug_glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib2f(indx, x, y);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib2f);
+}
+
+void Debug_glVertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib2fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 2 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib2fv);
+}
+
+void Debug_glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib3f(indx, x, y, z);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib3f);
+}
+
+void Debug_glVertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib3fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 3 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib3fv);
+}
+
+void Debug_glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLfloat x;
+        GLfloat y;
+        GLfloat z;
+        GLfloat w;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib4f(indx, x, y, z, w);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.x = x;
+    caller.y = y;
+    caller.z = z;
+    caller.w = w;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(x));
+    msg.set_arg2(ToInt(y));
+    msg.set_arg3(ToInt(z));
+    msg.set_arg4(ToInt(w));
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib4f);
+}
+
+void Debug_glVertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        const GLfloat* values;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttrib4fv(indx, values);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.values = values;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(ToInt(values));
+
+    // FIXME: check for pointer usage
+    msg.mutable_data()->assign(reinterpret_cast<const char *>(values), 4 * sizeof(GLfloat));
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttrib4fv);
+}
+
+// FIXME: this function has pointers, it should be hand written
+void Debug_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLuint indx;
+        GLint size;
+        GLenum type;
+        GLboolean normalized;
+        GLsizei stride;
+        const GLvoid* ptr;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+            getDbgContextThreadSpecific()->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+            return 0;
+        }
+    } caller;
+    caller.indx = indx;
+    caller.size = size;
+    caller.type = type;
+    caller.normalized = normalized;
+    caller.stride = stride;
+    caller.ptr = ptr;
+
+    msg.set_arg0(indx);
+    msg.set_arg1(size);
+    msg.set_arg2(type);
+    msg.set_arg3(normalized);
+    msg.set_arg4(stride);
+    msg.set_arg5(ToInt(ptr));
+
+    // FIXME: check for pointer usage
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glVertexAttribPointer);
+}
+
+void Debug_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLint x;
+        GLint y;
+        GLsizei width;
+        GLsizei height;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            _c->glViewport(x, y, width, height);
+            return 0;
+        }
+    } caller;
+    caller.x = x;
+    caller.y = y;
+    caller.width = width;
+    caller.height = height;
+
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glViewport);
+}
+
+// FIXME: the following functions should be written by hand
+void Debug_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+void Debug_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+void Debug_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+void Debug_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+void Debug_glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+void Debug_glGetBooleanv(GLenum pname, GLboolean* params);
+void Debug_glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
+void Debug_glGetFloatv(GLenum pname, GLfloat* params);
+void Debug_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+void Debug_glGetIntegerv(GLenum pname, GLint* params);
+void Debug_glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+void Debug_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
+void Debug_glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+void Debug_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+void Debug_glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+const GLubyte* Debug_glGetString(GLenum name);
+void Debug_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
+void Debug_glGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
+void Debug_glGetUniformfv(GLuint program, GLint location, GLfloat* params);
+void Debug_glGetUniformiv(GLuint program, GLint location, GLint* params);
+void Debug_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
+void Debug_glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
+void Debug_glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer);
+void Debug_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+void Debug_glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
+void Debug_glTexParameteriv(GLenum target, GLenum pname, const GLint* params);
+void Debug_glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
diff --git a/opengl/libs/GLES2_dbg/src/api.h b/opengl/libs/GLES2_dbg/src/api.h
new file mode 100644
index 0000000..be94dfc
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/api.h
@@ -0,0 +1,31 @@
+/*
+ ** 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.
+ */
+
+#define EXTEND_Debug_glCopyTexImage2D \
+    void * pixels = malloc(width * height * 4); \
+    getGLTraceThreadSpecific()->gl.glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); \
+    msg.set_data(pixels, width * height * 4); \
+    free(pixels);
+    
+#define EXTEND_Debug_glCopyTexSubImage2D EXTEND_Debug_glCopyTexImage2D
+
+#define EXTEND_Debug_glShaderSource \
+    std::string * const data = msg.mutable_data(); \
+    for (unsigned i = 0; i < count; i++) \
+        if (!length || length[i] < 0) \
+            data->append(string[i]); \
+        else \
+            data->append(string[i], length[i]);
\ No newline at end of file
diff --git a/opengl/libs/GLES2_dbg/src/caller.h b/opengl/libs/GLES2_dbg/src/caller.h
new file mode 100644
index 0000000..01bc4ea
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/caller.h
@@ -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.
+ */
+
+#include "src/header.h"
+
+
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
new file mode 100644
index 0000000..68514df
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -0,0 +1,243 @@
+/*
+ ** 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 "header.h"
+
+namespace android
+{
+
+DbgContext::DbgContext(const unsigned version, const gl_hooks_t * const hooks,
+                       const unsigned MAX_VERTEX_ATTRIBS)
+        : version(version), hooks(hooks)
+        , MAX_VERTEX_ATTRIBS(MAX_VERTEX_ATTRIBS)
+        , vertexAttribs(new VertexAttrib[MAX_VERTEX_ATTRIBS])
+        , hasNonVBOAttribs(false), indexBuffers(NULL), indexBuffer(NULL)
+{
+    for (unsigned i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+        vertexAttribs[i] = VertexAttrib();
+}
+
+DbgContext::~DbgContext()
+{
+    delete vertexAttribs;
+}
+
+DbgContext * CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks)
+{
+    assert(version < 2);
+    assert(GL_NO_ERROR == hooks->gl.glGetError());
+    GLint MAX_VERTEX_ATTRIBS = 0;
+    hooks->gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &MAX_VERTEX_ATTRIBS);
+    return new DbgContext(version, hooks, MAX_VERTEX_ATTRIBS);
+}
+
+void DestroyDbgContext(DbgContext * const dbg)
+{
+    delete dbg;
+}
+
+void DbgContext::Fetch(const unsigned index, std::string * const data) const
+{
+    // VBO data is already on client, just send user pointer data
+    for (unsigned i = 0; i < maxAttrib; i++) {
+        if (!vertexAttribs[i].enabled)
+            continue;
+        if (vertexAttribs[i].buffer > 0)
+            continue;
+        const char * ptr = (const char *)vertexAttribs[i].ptr;
+        ptr += index * vertexAttribs[i].stride;
+        data->append(ptr, vertexAttribs[i].elemSize);
+    }
+}
+
+void DbgContext::glUseProgram(GLuint program)
+{
+    assert(GL_NO_ERROR == hooks->gl.glGetError());
+
+    this->program = program;
+
+    GLint activeAttributes = 0;
+    hooks->gl.glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttributes);
+    maxAttrib = 0;
+    GLint maxNameLen = -1;
+    hooks->gl.glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLen);
+    char * name = new char [maxNameLen + 1];
+    name[maxNameLen] = 0;
+    // find total number of attribute slots used
+    for (unsigned i = 0; i < activeAttributes; i++) {
+        GLint size = -1;
+        GLenum type = -1;
+        hooks->gl.glGetActiveAttrib(program, i, maxNameLen + 1, NULL, &size, &type, name);
+        GLint slot = hooks->gl.glGetAttribLocation(program, name);
+        assert(slot >= 0);
+        switch (type) {
+        case GL_FLOAT:
+        case GL_FLOAT_VEC2:
+        case GL_FLOAT_VEC3:
+        case GL_FLOAT_VEC4:
+            slot += size;
+            break;
+        case GL_FLOAT_MAT2:
+            slot += size * 2;
+            break;
+        case GL_FLOAT_MAT3:
+            slot += size * 3;
+            break;
+        case GL_FLOAT_MAT4:
+            slot += size * 4;
+            break;
+        default:
+            assert(0);
+        }
+        if (slot > maxAttrib)
+            maxAttrib = slot;
+    }
+    delete name;
+}
+
+static bool HasNonVBOAttribs(const DbgContext * const ctx)
+{
+    bool need = false;
+    for (unsigned i = 0; !need && i < ctx->maxAttrib; i++)
+        if (ctx->vertexAttribs[i].enabled && ctx->vertexAttribs[i].buffer == 0)
+            need = true;
+    return need;
+}
+
+void DbgContext::glVertexAttribPointer(GLuint indx, GLint size, GLenum type,
+                                       GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+    assert(GL_NO_ERROR == hooks->gl.glGetError());
+    assert(indx < MAX_VERTEX_ATTRIBS);
+    vertexAttribs[indx].size = size;
+    vertexAttribs[indx].type = type;
+    vertexAttribs[indx].normalized = normalized;
+    switch (type) {
+    case GL_FLOAT:
+        vertexAttribs[indx].elemSize = sizeof(GLfloat) * size;
+        break;
+    case GL_INT:
+    case GL_UNSIGNED_INT:
+        vertexAttribs[indx].elemSize = sizeof(GLint) * size;
+        break;
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+        vertexAttribs[indx].elemSize = sizeof(GLshort) * size;
+        break;
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+        vertexAttribs[indx].elemSize = sizeof(GLbyte) * size;
+        break;
+    default:
+        assert(0);
+    }
+    if (0 == stride)
+        stride = vertexAttribs[indx].elemSize;
+    vertexAttribs[indx].stride = stride;
+    vertexAttribs[indx].ptr = ptr;
+    hooks->gl.glGetVertexAttribiv(indx, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
+                                  (GLint *)&vertexAttribs[indx].buffer);
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+void DbgContext::glEnableVertexAttribArray(GLuint index)
+{
+    assert(index < MAX_VERTEX_ATTRIBS);
+    vertexAttribs[index].enabled = true;
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+void DbgContext::glDisableVertexAttribArray(GLuint index)
+{
+    assert(index < MAX_VERTEX_ATTRIBS);
+    vertexAttribs[index].enabled = false;
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+void DbgContext::glBindBuffer(GLenum target, GLuint buffer)
+{
+    if (GL_ELEMENT_ARRAY_BUFFER != target)
+        return;
+    if (0 == buffer) {
+        indexBuffer = NULL;
+        return;
+    }
+    VBO * b = indexBuffers;
+    indexBuffer = NULL;
+    while (b) {
+        if (b->name == buffer) {
+            assert(GL_ELEMENT_ARRAY_BUFFER == b->target);
+            indexBuffer = b;
+            break;
+        }
+        b = b->next;
+    }
+    if (!indexBuffer)
+        indexBuffer = indexBuffers = new VBO(buffer, target, indexBuffers);
+}
+
+void DbgContext::glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+    if (GL_ELEMENT_ARRAY_BUFFER != target)
+        return;
+    assert(indexBuffer);
+    assert(size >= 0);
+    indexBuffer->size = size;
+    indexBuffer->data = realloc(indexBuffer->data, size);
+    memcpy(indexBuffer->data, data, size);
+}
+
+void DbgContext::glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+    if (GL_ELEMENT_ARRAY_BUFFER != target)
+        return;
+    assert(indexBuffer);
+    assert(size >= 0);
+    assert(offset >= 0);
+    assert(offset + size <= indexBuffer->size);
+    memcpy((char *)indexBuffer->data + offset, data, size);
+}
+
+void DbgContext::glDeleteBuffers(GLsizei n, const GLuint *buffers)
+{
+    for (unsigned i = 0; i < n; i++) {
+        for (unsigned j = 0; j < MAX_VERTEX_ATTRIBS; j++)
+            if (buffers[i] == vertexAttribs[j].buffer) {
+                vertexAttribs[j].buffer = 0;
+                vertexAttribs[j].enabled = false;
+            }
+        VBO * b = indexBuffers, * previous = NULL;
+        while (b) {
+            if (b->name == buffers[i]) {
+                assert(GL_ELEMENT_ARRAY_BUFFER == b->target);
+                if (indexBuffer == b)
+                    indexBuffer = NULL;
+                if (previous)
+                    previous->next = b->next;
+                else
+                    indexBuffers = b->next;
+                free(b->data);
+                delete b;
+                break;
+            }
+            previous = b;
+            b = b->next;
+        }
+    }
+    hasNonVBOAttribs = HasNonVBOAttribs(this);
+}
+
+}; // namespace android
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
new file mode 100644
index 0000000..4083c44
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
@@ -0,0 +1,1252 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "debugger_message.pb.h"
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace android {
+namespace glesv2debugger {
+
+void protobuf_ShutdownFile_debugger_5fmessage_2eproto() {
+  delete Message::default_instance_;
+}
+
+void protobuf_AddDesc_debugger_5fmessage_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  Message::default_instance_ = new Message();
+  Message::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_debugger_5fmessage_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_debugger_5fmessage_2eproto {
+  StaticDescriptorInitializer_debugger_5fmessage_2eproto() {
+    protobuf_AddDesc_debugger_5fmessage_2eproto();
+  }
+} static_descriptor_initializer_debugger_5fmessage_2eproto_;
+
+
+// ===================================================================
+
+bool Message_Function_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+    case 50:
+    case 51:
+    case 52:
+    case 53:
+    case 54:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
+    case 59:
+    case 60:
+    case 61:
+    case 62:
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+    case 77:
+    case 78:
+    case 79:
+    case 80:
+    case 81:
+    case 82:
+    case 83:
+    case 84:
+    case 85:
+    case 86:
+    case 87:
+    case 88:
+    case 89:
+    case 90:
+    case 91:
+    case 92:
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+    case 105:
+    case 106:
+    case 107:
+    case 108:
+    case 109:
+    case 110:
+    case 111:
+    case 112:
+    case 113:
+    case 114:
+    case 115:
+    case 116:
+    case 117:
+    case 118:
+    case 119:
+    case 120:
+    case 121:
+    case 122:
+    case 123:
+    case 124:
+    case 125:
+    case 126:
+    case 127:
+    case 128:
+    case 129:
+    case 130:
+    case 131:
+    case 132:
+    case 133:
+    case 134:
+    case 135:
+    case 136:
+    case 137:
+    case 138:
+    case 139:
+    case 140:
+    case 141:
+    case 142:
+    case 143:
+    case 144:
+    case 145:
+    case 146:
+    case 147:
+    case 148:
+    case 149:
+    case 150:
+    case 151:
+    case 152:
+    case 153:
+    case 154:
+    case 155:
+    case 156:
+    case 157:
+    case 158:
+    case 159:
+    case 160:
+    case 161:
+    case 162:
+    case 163:
+    case 164:
+    case 165:
+    case 166:
+    case 167:
+    case 168:
+    case 169:
+    case 170:
+    case 171:
+    case 172:
+    case 173:
+    case 174:
+    case 175:
+    case 176:
+    case 177:
+    case 178:
+    case 179:
+    case 180:
+    case 181:
+    case 182:
+    case 183:
+    case 184:
+    case 185:
+    case 186:
+    case 187:
+    case 188:
+    case 189:
+    case 190:
+    case 191:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Function Message::glActiveTexture;
+const Message_Function Message::glAttachShader;
+const Message_Function Message::glBindAttribLocation;
+const Message_Function Message::glBindBuffer;
+const Message_Function Message::glBindFramebuffer;
+const Message_Function Message::glBindRenderbuffer;
+const Message_Function Message::glBindTexture;
+const Message_Function Message::glBlendColor;
+const Message_Function Message::glBlendEquation;
+const Message_Function Message::glBlendEquationSeparate;
+const Message_Function Message::glBlendFunc;
+const Message_Function Message::glBlendFuncSeparate;
+const Message_Function Message::glBufferData;
+const Message_Function Message::glBufferSubData;
+const Message_Function Message::glCheckFramebufferStatus;
+const Message_Function Message::glClear;
+const Message_Function Message::glClearColor;
+const Message_Function Message::glClearDepthf;
+const Message_Function Message::glClearStencil;
+const Message_Function Message::glColorMask;
+const Message_Function Message::glCompileShader;
+const Message_Function Message::glCompressedTexImage2D;
+const Message_Function Message::glCompressedTexSubImage2D;
+const Message_Function Message::glCopyTexImage2D;
+const Message_Function Message::glCopyTexSubImage2D;
+const Message_Function Message::glCreateProgram;
+const Message_Function Message::glCreateShader;
+const Message_Function Message::glCullFace;
+const Message_Function Message::glDeleteBuffers;
+const Message_Function Message::glDeleteFramebuffers;
+const Message_Function Message::glDeleteProgram;
+const Message_Function Message::glDeleteRenderbuffers;
+const Message_Function Message::glDeleteShader;
+const Message_Function Message::glDeleteTextures;
+const Message_Function Message::glDepthFunc;
+const Message_Function Message::glDepthMask;
+const Message_Function Message::glDepthRangef;
+const Message_Function Message::glDetachShader;
+const Message_Function Message::glDisable;
+const Message_Function Message::glDisableVertexAttribArray;
+const Message_Function Message::glDrawArrays;
+const Message_Function Message::glDrawElements;
+const Message_Function Message::glEnable;
+const Message_Function Message::glEnableVertexAttribArray;
+const Message_Function Message::glFinish;
+const Message_Function Message::glFlush;
+const Message_Function Message::glFramebufferRenderbuffer;
+const Message_Function Message::glFramebufferTexture2D;
+const Message_Function Message::glFrontFace;
+const Message_Function Message::glGenBuffers;
+const Message_Function Message::glGenerateMipmap;
+const Message_Function Message::glGenFramebuffers;
+const Message_Function Message::glGenRenderbuffers;
+const Message_Function Message::glGenTextures;
+const Message_Function Message::glGetActiveAttrib;
+const Message_Function Message::glGetActiveUniform;
+const Message_Function Message::glGetAttachedShaders;
+const Message_Function Message::glGetAttribLocation;
+const Message_Function Message::glGetBooleanv;
+const Message_Function Message::glGetBufferParameteriv;
+const Message_Function Message::glGetError;
+const Message_Function Message::glGetFloatv;
+const Message_Function Message::glGetFramebufferAttachmentParameteriv;
+const Message_Function Message::glGetIntegerv;
+const Message_Function Message::glGetProgramiv;
+const Message_Function Message::glGetProgramInfoLog;
+const Message_Function Message::glGetRenderbufferParameteriv;
+const Message_Function Message::glGetShaderiv;
+const Message_Function Message::glGetShaderInfoLog;
+const Message_Function Message::glGetShaderPrecisionFormat;
+const Message_Function Message::glGetShaderSource;
+const Message_Function Message::glGetString;
+const Message_Function Message::glGetTexParameterfv;
+const Message_Function Message::glGetTexParameteriv;
+const Message_Function Message::glGetUniformfv;
+const Message_Function Message::glGetUniformiv;
+const Message_Function Message::glGetUniformLocation;
+const Message_Function Message::glGetVertexAttribfv;
+const Message_Function Message::glGetVertexAttribiv;
+const Message_Function Message::glGetVertexAttribPointerv;
+const Message_Function Message::glHint;
+const Message_Function Message::glIsBuffer;
+const Message_Function Message::glIsEnabled;
+const Message_Function Message::glIsFramebuffer;
+const Message_Function Message::glIsProgram;
+const Message_Function Message::glIsRenderbuffer;
+const Message_Function Message::glIsShader;
+const Message_Function Message::glIsTexture;
+const Message_Function Message::glLineWidth;
+const Message_Function Message::glLinkProgram;
+const Message_Function Message::glPixelStorei;
+const Message_Function Message::glPolygonOffset;
+const Message_Function Message::glReadPixels;
+const Message_Function Message::glReleaseShaderCompiler;
+const Message_Function Message::glRenderbufferStorage;
+const Message_Function Message::glSampleCoverage;
+const Message_Function Message::glScissor;
+const Message_Function Message::glShaderBinary;
+const Message_Function Message::glShaderSource;
+const Message_Function Message::glStencilFunc;
+const Message_Function Message::glStencilFuncSeparate;
+const Message_Function Message::glStencilMask;
+const Message_Function Message::glStencilMaskSeparate;
+const Message_Function Message::glStencilOp;
+const Message_Function Message::glStencilOpSeparate;
+const Message_Function Message::glTexImage2D;
+const Message_Function Message::glTexParameterf;
+const Message_Function Message::glTexParameterfv;
+const Message_Function Message::glTexParameteri;
+const Message_Function Message::glTexParameteriv;
+const Message_Function Message::glTexSubImage2D;
+const Message_Function Message::glUniform1f;
+const Message_Function Message::glUniform1fv;
+const Message_Function Message::glUniform1i;
+const Message_Function Message::glUniform1iv;
+const Message_Function Message::glUniform2f;
+const Message_Function Message::glUniform2fv;
+const Message_Function Message::glUniform2i;
+const Message_Function Message::glUniform2iv;
+const Message_Function Message::glUniform3f;
+const Message_Function Message::glUniform3fv;
+const Message_Function Message::glUniform3i;
+const Message_Function Message::glUniform3iv;
+const Message_Function Message::glUniform4f;
+const Message_Function Message::glUniform4fv;
+const Message_Function Message::glUniform4i;
+const Message_Function Message::glUniform4iv;
+const Message_Function Message::glUniformMatrix2fv;
+const Message_Function Message::glUniformMatrix3fv;
+const Message_Function Message::glUniformMatrix4fv;
+const Message_Function Message::glUseProgram;
+const Message_Function Message::glValidateProgram;
+const Message_Function Message::glVertexAttrib1f;
+const Message_Function Message::glVertexAttrib1fv;
+const Message_Function Message::glVertexAttrib2f;
+const Message_Function Message::glVertexAttrib2fv;
+const Message_Function Message::glVertexAttrib3f;
+const Message_Function Message::glVertexAttrib3fv;
+const Message_Function Message::glVertexAttrib4f;
+const Message_Function Message::glVertexAttrib4fv;
+const Message_Function Message::glVertexAttribPointer;
+const Message_Function Message::glViewport;
+const Message_Function Message::eglGetDisplay;
+const Message_Function Message::eglInitialize;
+const Message_Function Message::eglTerminate;
+const Message_Function Message::eglGetConfigs;
+const Message_Function Message::eglChooseConfig;
+const Message_Function Message::eglGetConfigAttrib;
+const Message_Function Message::eglCreateWindowSurface;
+const Message_Function Message::eglCreatePixmapSurface;
+const Message_Function Message::eglCreatePbufferSurface;
+const Message_Function Message::eglDestroySurface;
+const Message_Function Message::eglQuerySurface;
+const Message_Function Message::eglCreateContext;
+const Message_Function Message::eglDestroyContext;
+const Message_Function Message::eglMakeCurrent;
+const Message_Function Message::eglGetCurrentContext;
+const Message_Function Message::eglGetCurrentSurface;
+const Message_Function Message::eglGetCurrentDisplay;
+const Message_Function Message::eglQueryContext;
+const Message_Function Message::eglWaitGL;
+const Message_Function Message::eglWaitNative;
+const Message_Function Message::eglSwapBuffers;
+const Message_Function Message::eglCopyBuffers;
+const Message_Function Message::eglGetError;
+const Message_Function Message::eglQueryString;
+const Message_Function Message::eglGetProcAddress;
+const Message_Function Message::eglSurfaceAttrib;
+const Message_Function Message::eglBindTexImage;
+const Message_Function Message::eglReleaseTexImage;
+const Message_Function Message::eglSwapInterval;
+const Message_Function Message::eglBindAPI;
+const Message_Function Message::eglQueryAPI;
+const Message_Function Message::eglWaitClient;
+const Message_Function Message::eglReleaseThread;
+const Message_Function Message::eglCreatePbufferFromClientBuffer;
+const Message_Function Message::eglLockSurfaceKHR;
+const Message_Function Message::eglUnlockSurfaceKHR;
+const Message_Function Message::eglCreateImageKHR;
+const Message_Function Message::eglDestroyImageKHR;
+const Message_Function Message::eglCreateSyncKHR;
+const Message_Function Message::eglDestroySyncKHR;
+const Message_Function Message::eglClientWaitSyncKHR;
+const Message_Function Message::eglGetSyncAttribKHR;
+const Message_Function Message::eglSetSwapRectangleANDROID;
+const Message_Function Message::eglGetRenderBufferANDROID;
+const Message_Function Message::ACK;
+const Message_Function Message::NEG;
+const Message_Function Message::CONTINUE;
+const Message_Function Message::SKIP;
+const Message_Function Message::SETPROP;
+const Message_Function Message::CAPTURE;
+const Message_Function Message::Function_MIN;
+const Message_Function Message::Function_MAX;
+const int Message::Function_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_Type_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Type Message::BeforeCall;
+const Message_Type Message::AfterCall;
+const Message_Type Message::Response;
+const Message_Type Message::Type_MIN;
+const Message_Type Message::Type_MAX;
+const int Message::Type_ARRAYSIZE;
+#endif  // _MSC_VER
+bool Message_Prop_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Message_Prop Message::Capture;
+const Message_Prop Message::TimeMode;
+const Message_Prop Message::Prop_MIN;
+const Message_Prop Message::Prop_MAX;
+const int Message::Prop_ARRAYSIZE;
+#endif  // _MSC_VER
+const ::std::string Message::_default_data_;
+#ifndef _MSC_VER
+const int Message::kContextIdFieldNumber;
+const int Message::kFunctionFieldNumber;
+const int Message::kTypeFieldNumber;
+const int Message::kExpectResponseFieldNumber;
+const int Message::kRetFieldNumber;
+const int Message::kArg0FieldNumber;
+const int Message::kArg1FieldNumber;
+const int Message::kArg2FieldNumber;
+const int Message::kArg3FieldNumber;
+const int Message::kArg4FieldNumber;
+const int Message::kArg5FieldNumber;
+const int Message::kArg6FieldNumber;
+const int Message::kArg7FieldNumber;
+const int Message::kArg8FieldNumber;
+const int Message::kDataFieldNumber;
+const int Message::kTimeFieldNumber;
+const int Message::kPropFieldNumber;
+const int Message::kClockFieldNumber;
+#endif  // !_MSC_VER
+
+Message::Message()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+}
+
+void Message::InitAsDefaultInstance() {
+}
+
+Message::Message(const Message& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void Message::SharedCtor() {
+  _cached_size_ = 0;
+  context_id_ = 0;
+  function_ = 187;
+  type_ = 0;
+  expect_response_ = false;
+  ret_ = 0;
+  arg0_ = 0;
+  arg1_ = 0;
+  arg2_ = 0;
+  arg3_ = 0;
+  arg4_ = 0;
+  arg5_ = 0;
+  arg6_ = 0;
+  arg7_ = 0;
+  arg8_ = 0;
+  data_ = const_cast< ::std::string*>(&_default_data_);
+  time_ = 0;
+  prop_ = 0;
+  clock_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+Message::~Message() {
+  SharedDtor();
+}
+
+void Message::SharedDtor() {
+  if (data_ != &_default_data_) {
+    delete data_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void Message::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const Message& Message::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_debugger_5fmessage_2eproto();  return *default_instance_;
+}
+
+Message* Message::default_instance_ = NULL;
+
+Message* Message::New() const {
+  return new Message;
+}
+
+void Message::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    context_id_ = 0;
+    function_ = 187;
+    type_ = 0;
+    expect_response_ = false;
+    ret_ = 0;
+    arg0_ = 0;
+    arg1_ = 0;
+    arg2_ = 0;
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    arg3_ = 0;
+    arg4_ = 0;
+    arg5_ = 0;
+    arg6_ = 0;
+    arg7_ = 0;
+    arg8_ = 0;
+    if (_has_bit(14)) {
+      if (data_ != &_default_data_) {
+        data_->clear();
+      }
+    }
+    time_ = 0;
+  }
+  if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    prop_ = 0;
+    clock_ = 0;
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+bool Message::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required int32 context_id = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &context_id_)));
+          _set_bit(0);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(16)) goto parse_function;
+        break;
+      }
+      
+      // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_function:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Function_IsValid(value)) {
+            set_function(static_cast< ::com::android::glesv2debugger::Message_Function >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(24)) goto parse_type;
+        break;
+      }
+      
+      // required .com.android.glesv2debugger.Message.Type type = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_type:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Type_IsValid(value)) {
+            set_type(static_cast< ::com::android::glesv2debugger::Message_Type >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(32)) goto parse_expect_response;
+        break;
+      }
+      
+      // required bool expect_response = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_expect_response:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &expect_response_)));
+          _set_bit(3);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(40)) goto parse_ret;
+        break;
+      }
+      
+      // optional int32 ret = 5;
+      case 5: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_ret:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &ret_)));
+          _set_bit(4);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(48)) goto parse_arg0;
+        break;
+      }
+      
+      // optional int32 arg0 = 6;
+      case 6: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg0:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg0_)));
+          _set_bit(5);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(56)) goto parse_arg1;
+        break;
+      }
+      
+      // optional int32 arg1 = 7;
+      case 7: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg1:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg1_)));
+          _set_bit(6);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(64)) goto parse_arg2;
+        break;
+      }
+      
+      // optional int32 arg2 = 8;
+      case 8: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg2:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg2_)));
+          _set_bit(7);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(72)) goto parse_arg3;
+        break;
+      }
+      
+      // optional int32 arg3 = 9;
+      case 9: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg3:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg3_)));
+          _set_bit(8);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(82)) goto parse_data;
+        break;
+      }
+      
+      // optional bytes data = 10;
+      case 10: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_data:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_data()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(93)) goto parse_time;
+        break;
+      }
+      
+      // optional float time = 11;
+      case 11: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_time:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &time_)));
+          _set_bit(15);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(128)) goto parse_arg4;
+        break;
+      }
+      
+      // optional int32 arg4 = 16;
+      case 16: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg4:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg4_)));
+          _set_bit(9);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(136)) goto parse_arg5;
+        break;
+      }
+      
+      // optional int32 arg5 = 17;
+      case 17: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg5:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg5_)));
+          _set_bit(10);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(144)) goto parse_arg6;
+        break;
+      }
+      
+      // optional int32 arg6 = 18;
+      case 18: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg6:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg6_)));
+          _set_bit(11);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(152)) goto parse_arg7;
+        break;
+      }
+      
+      // optional int32 arg7 = 19;
+      case 19: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg7:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg7_)));
+          _set_bit(12);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(160)) goto parse_arg8;
+        break;
+      }
+      
+      // optional int32 arg8 = 20;
+      case 20: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_arg8:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &arg8_)));
+          _set_bit(13);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(168)) goto parse_prop;
+        break;
+      }
+      
+      // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+      case 21: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_prop:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::android::glesv2debugger::Message_Prop_IsValid(value)) {
+            set_prop(static_cast< ::com::android::glesv2debugger::Message_Prop >(value));
+          }
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(181)) goto parse_clock;
+        break;
+      }
+      
+      // optional float clock = 22;
+      case 22: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
+         parse_clock:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &clock_)));
+          _set_bit(17);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void Message::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // required int32 context_id = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->context_id(), output);
+  }
+  
+  // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->function(), output);
+  }
+  
+  // required .com.android.glesv2debugger.Message.Type type = 3;
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->type(), output);
+  }
+  
+  // required bool expect_response = 4;
+  if (_has_bit(3)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->expect_response(), output);
+  }
+  
+  // optional int32 ret = 5;
+  if (_has_bit(4)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(5, this->ret(), output);
+  }
+  
+  // optional int32 arg0 = 6;
+  if (_has_bit(5)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(6, this->arg0(), output);
+  }
+  
+  // optional int32 arg1 = 7;
+  if (_has_bit(6)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->arg1(), output);
+  }
+  
+  // optional int32 arg2 = 8;
+  if (_has_bit(7)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(8, this->arg2(), output);
+  }
+  
+  // optional int32 arg3 = 9;
+  if (_has_bit(8)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->arg3(), output);
+  }
+  
+  // optional bytes data = 10;
+  if (_has_bit(14)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytes(
+      10, this->data(), output);
+  }
+  
+  // optional float time = 11;
+  if (_has_bit(15)) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(11, this->time(), output);
+  }
+  
+  // optional int32 arg4 = 16;
+  if (_has_bit(9)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(16, this->arg4(), output);
+  }
+  
+  // optional int32 arg5 = 17;
+  if (_has_bit(10)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(17, this->arg5(), output);
+  }
+  
+  // optional int32 arg6 = 18;
+  if (_has_bit(11)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(18, this->arg6(), output);
+  }
+  
+  // optional int32 arg7 = 19;
+  if (_has_bit(12)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(19, this->arg7(), output);
+  }
+  
+  // optional int32 arg8 = 20;
+  if (_has_bit(13)) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(20, this->arg8(), output);
+  }
+  
+  // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+  if (_has_bit(16)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      21, this->prop(), output);
+  }
+  
+  // optional float clock = 22;
+  if (_has_bit(17)) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(22, this->clock(), output);
+  }
+  
+}
+
+int Message::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required int32 context_id = 1;
+    if (has_context_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->context_id());
+    }
+    
+    // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+    if (has_function()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->function());
+    }
+    
+    // required .com.android.glesv2debugger.Message.Type type = 3;
+    if (has_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
+    }
+    
+    // required bool expect_response = 4;
+    if (has_expect_response()) {
+      total_size += 1 + 1;
+    }
+    
+    // optional int32 ret = 5;
+    if (has_ret()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->ret());
+    }
+    
+    // optional int32 arg0 = 6;
+    if (has_arg0()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg0());
+    }
+    
+    // optional int32 arg1 = 7;
+    if (has_arg1()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg1());
+    }
+    
+    // optional int32 arg2 = 8;
+    if (has_arg2()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg2());
+    }
+    
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // optional int32 arg3 = 9;
+    if (has_arg3()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg3());
+    }
+    
+    // optional int32 arg4 = 16;
+    if (has_arg4()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg4());
+    }
+    
+    // optional int32 arg5 = 17;
+    if (has_arg5()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg5());
+    }
+    
+    // optional int32 arg6 = 18;
+    if (has_arg6()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg6());
+    }
+    
+    // optional int32 arg7 = 19;
+    if (has_arg7()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg7());
+    }
+    
+    // optional int32 arg8 = 20;
+    if (has_arg8()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->arg8());
+    }
+    
+    // optional bytes data = 10;
+    if (has_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->data());
+    }
+    
+    // optional float time = 11;
+    if (has_time()) {
+      total_size += 1 + 4;
+    }
+    
+  }
+  if (_has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+    if (has_prop()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->prop());
+    }
+    
+    // optional float clock = 22;
+    if (has_clock()) {
+      total_size += 2 + 4;
+    }
+    
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Message::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const Message*>(&from));
+}
+
+void Message::MergeFrom(const Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_context_id(from.context_id());
+    }
+    if (from._has_bit(1)) {
+      set_function(from.function());
+    }
+    if (from._has_bit(2)) {
+      set_type(from.type());
+    }
+    if (from._has_bit(3)) {
+      set_expect_response(from.expect_response());
+    }
+    if (from._has_bit(4)) {
+      set_ret(from.ret());
+    }
+    if (from._has_bit(5)) {
+      set_arg0(from.arg0());
+    }
+    if (from._has_bit(6)) {
+      set_arg1(from.arg1());
+    }
+    if (from._has_bit(7)) {
+      set_arg2(from.arg2());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from._has_bit(8)) {
+      set_arg3(from.arg3());
+    }
+    if (from._has_bit(9)) {
+      set_arg4(from.arg4());
+    }
+    if (from._has_bit(10)) {
+      set_arg5(from.arg5());
+    }
+    if (from._has_bit(11)) {
+      set_arg6(from.arg6());
+    }
+    if (from._has_bit(12)) {
+      set_arg7(from.arg7());
+    }
+    if (from._has_bit(13)) {
+      set_arg8(from.arg8());
+    }
+    if (from._has_bit(14)) {
+      set_data(from.data());
+    }
+    if (from._has_bit(15)) {
+      set_time(from.time());
+    }
+  }
+  if (from._has_bits_[16 / 32] & (0xffu << (16 % 32))) {
+    if (from._has_bit(16)) {
+      set_prop(from.prop());
+    }
+    if (from._has_bit(17)) {
+      set_clock(from.clock());
+    }
+  }
+}
+
+void Message::CopyFrom(const Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Message::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false;
+  
+  return true;
+}
+
+void Message::Swap(Message* other) {
+  if (other != this) {
+    std::swap(context_id_, other->context_id_);
+    std::swap(function_, other->function_);
+    std::swap(type_, other->type_);
+    std::swap(expect_response_, other->expect_response_);
+    std::swap(ret_, other->ret_);
+    std::swap(arg0_, other->arg0_);
+    std::swap(arg1_, other->arg1_);
+    std::swap(arg2_, other->arg2_);
+    std::swap(arg3_, other->arg3_);
+    std::swap(arg4_, other->arg4_);
+    std::swap(arg5_, other->arg5_);
+    std::swap(arg6_, other->arg6_);
+    std::swap(arg7_, other->arg7_);
+    std::swap(arg8_, other->arg8_);
+    std::swap(data_, other->data_);
+    std::swap(time_, other->time_);
+    std::swap(prop_, other->prop_);
+    std::swap(clock_, other->clock_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string Message::GetTypeName() const {
+  return "com.android.glesv2debugger.Message";
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace glesv2debugger
+}  // namespace android
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
new file mode 100644
index 0000000..3f2b842
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
@@ -0,0 +1,1036 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: debugger_message.proto
+
+#ifndef PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
+#define PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2003000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace android {
+namespace glesv2debugger {
+
+// Internal implementation detail -- do not call these.
+void  protobuf_AddDesc_debugger_5fmessage_2eproto();
+void protobuf_AssignDesc_debugger_5fmessage_2eproto();
+void protobuf_ShutdownFile_debugger_5fmessage_2eproto();
+
+class Message;
+
+enum Message_Function {
+  Message_Function_glActiveTexture = 0,
+  Message_Function_glAttachShader = 1,
+  Message_Function_glBindAttribLocation = 2,
+  Message_Function_glBindBuffer = 3,
+  Message_Function_glBindFramebuffer = 4,
+  Message_Function_glBindRenderbuffer = 5,
+  Message_Function_glBindTexture = 6,
+  Message_Function_glBlendColor = 7,
+  Message_Function_glBlendEquation = 8,
+  Message_Function_glBlendEquationSeparate = 9,
+  Message_Function_glBlendFunc = 10,
+  Message_Function_glBlendFuncSeparate = 11,
+  Message_Function_glBufferData = 12,
+  Message_Function_glBufferSubData = 13,
+  Message_Function_glCheckFramebufferStatus = 14,
+  Message_Function_glClear = 15,
+  Message_Function_glClearColor = 16,
+  Message_Function_glClearDepthf = 17,
+  Message_Function_glClearStencil = 18,
+  Message_Function_glColorMask = 19,
+  Message_Function_glCompileShader = 20,
+  Message_Function_glCompressedTexImage2D = 21,
+  Message_Function_glCompressedTexSubImage2D = 22,
+  Message_Function_glCopyTexImage2D = 23,
+  Message_Function_glCopyTexSubImage2D = 24,
+  Message_Function_glCreateProgram = 25,
+  Message_Function_glCreateShader = 26,
+  Message_Function_glCullFace = 27,
+  Message_Function_glDeleteBuffers = 28,
+  Message_Function_glDeleteFramebuffers = 29,
+  Message_Function_glDeleteProgram = 30,
+  Message_Function_glDeleteRenderbuffers = 31,
+  Message_Function_glDeleteShader = 32,
+  Message_Function_glDeleteTextures = 33,
+  Message_Function_glDepthFunc = 34,
+  Message_Function_glDepthMask = 35,
+  Message_Function_glDepthRangef = 36,
+  Message_Function_glDetachShader = 37,
+  Message_Function_glDisable = 38,
+  Message_Function_glDisableVertexAttribArray = 39,
+  Message_Function_glDrawArrays = 40,
+  Message_Function_glDrawElements = 41,
+  Message_Function_glEnable = 42,
+  Message_Function_glEnableVertexAttribArray = 43,
+  Message_Function_glFinish = 44,
+  Message_Function_glFlush = 45,
+  Message_Function_glFramebufferRenderbuffer = 46,
+  Message_Function_glFramebufferTexture2D = 47,
+  Message_Function_glFrontFace = 48,
+  Message_Function_glGenBuffers = 49,
+  Message_Function_glGenerateMipmap = 50,
+  Message_Function_glGenFramebuffers = 51,
+  Message_Function_glGenRenderbuffers = 52,
+  Message_Function_glGenTextures = 53,
+  Message_Function_glGetActiveAttrib = 54,
+  Message_Function_glGetActiveUniform = 55,
+  Message_Function_glGetAttachedShaders = 56,
+  Message_Function_glGetAttribLocation = 57,
+  Message_Function_glGetBooleanv = 58,
+  Message_Function_glGetBufferParameteriv = 59,
+  Message_Function_glGetError = 60,
+  Message_Function_glGetFloatv = 61,
+  Message_Function_glGetFramebufferAttachmentParameteriv = 62,
+  Message_Function_glGetIntegerv = 63,
+  Message_Function_glGetProgramiv = 64,
+  Message_Function_glGetProgramInfoLog = 65,
+  Message_Function_glGetRenderbufferParameteriv = 66,
+  Message_Function_glGetShaderiv = 67,
+  Message_Function_glGetShaderInfoLog = 68,
+  Message_Function_glGetShaderPrecisionFormat = 69,
+  Message_Function_glGetShaderSource = 70,
+  Message_Function_glGetString = 71,
+  Message_Function_glGetTexParameterfv = 72,
+  Message_Function_glGetTexParameteriv = 73,
+  Message_Function_glGetUniformfv = 74,
+  Message_Function_glGetUniformiv = 75,
+  Message_Function_glGetUniformLocation = 76,
+  Message_Function_glGetVertexAttribfv = 77,
+  Message_Function_glGetVertexAttribiv = 78,
+  Message_Function_glGetVertexAttribPointerv = 79,
+  Message_Function_glHint = 80,
+  Message_Function_glIsBuffer = 81,
+  Message_Function_glIsEnabled = 82,
+  Message_Function_glIsFramebuffer = 83,
+  Message_Function_glIsProgram = 84,
+  Message_Function_glIsRenderbuffer = 85,
+  Message_Function_glIsShader = 86,
+  Message_Function_glIsTexture = 87,
+  Message_Function_glLineWidth = 88,
+  Message_Function_glLinkProgram = 89,
+  Message_Function_glPixelStorei = 90,
+  Message_Function_glPolygonOffset = 91,
+  Message_Function_glReadPixels = 92,
+  Message_Function_glReleaseShaderCompiler = 93,
+  Message_Function_glRenderbufferStorage = 94,
+  Message_Function_glSampleCoverage = 95,
+  Message_Function_glScissor = 96,
+  Message_Function_glShaderBinary = 97,
+  Message_Function_glShaderSource = 98,
+  Message_Function_glStencilFunc = 99,
+  Message_Function_glStencilFuncSeparate = 100,
+  Message_Function_glStencilMask = 101,
+  Message_Function_glStencilMaskSeparate = 102,
+  Message_Function_glStencilOp = 103,
+  Message_Function_glStencilOpSeparate = 104,
+  Message_Function_glTexImage2D = 105,
+  Message_Function_glTexParameterf = 106,
+  Message_Function_glTexParameterfv = 107,
+  Message_Function_glTexParameteri = 108,
+  Message_Function_glTexParameteriv = 109,
+  Message_Function_glTexSubImage2D = 110,
+  Message_Function_glUniform1f = 111,
+  Message_Function_glUniform1fv = 112,
+  Message_Function_glUniform1i = 113,
+  Message_Function_glUniform1iv = 114,
+  Message_Function_glUniform2f = 115,
+  Message_Function_glUniform2fv = 116,
+  Message_Function_glUniform2i = 117,
+  Message_Function_glUniform2iv = 118,
+  Message_Function_glUniform3f = 119,
+  Message_Function_glUniform3fv = 120,
+  Message_Function_glUniform3i = 121,
+  Message_Function_glUniform3iv = 122,
+  Message_Function_glUniform4f = 123,
+  Message_Function_glUniform4fv = 124,
+  Message_Function_glUniform4i = 125,
+  Message_Function_glUniform4iv = 126,
+  Message_Function_glUniformMatrix2fv = 127,
+  Message_Function_glUniformMatrix3fv = 128,
+  Message_Function_glUniformMatrix4fv = 129,
+  Message_Function_glUseProgram = 130,
+  Message_Function_glValidateProgram = 131,
+  Message_Function_glVertexAttrib1f = 132,
+  Message_Function_glVertexAttrib1fv = 133,
+  Message_Function_glVertexAttrib2f = 134,
+  Message_Function_glVertexAttrib2fv = 135,
+  Message_Function_glVertexAttrib3f = 136,
+  Message_Function_glVertexAttrib3fv = 137,
+  Message_Function_glVertexAttrib4f = 138,
+  Message_Function_glVertexAttrib4fv = 139,
+  Message_Function_glVertexAttribPointer = 140,
+  Message_Function_glViewport = 141,
+  Message_Function_eglGetDisplay = 142,
+  Message_Function_eglInitialize = 143,
+  Message_Function_eglTerminate = 144,
+  Message_Function_eglGetConfigs = 145,
+  Message_Function_eglChooseConfig = 146,
+  Message_Function_eglGetConfigAttrib = 147,
+  Message_Function_eglCreateWindowSurface = 148,
+  Message_Function_eglCreatePixmapSurface = 149,
+  Message_Function_eglCreatePbufferSurface = 150,
+  Message_Function_eglDestroySurface = 151,
+  Message_Function_eglQuerySurface = 152,
+  Message_Function_eglCreateContext = 153,
+  Message_Function_eglDestroyContext = 154,
+  Message_Function_eglMakeCurrent = 155,
+  Message_Function_eglGetCurrentContext = 156,
+  Message_Function_eglGetCurrentSurface = 157,
+  Message_Function_eglGetCurrentDisplay = 158,
+  Message_Function_eglQueryContext = 159,
+  Message_Function_eglWaitGL = 160,
+  Message_Function_eglWaitNative = 161,
+  Message_Function_eglSwapBuffers = 162,
+  Message_Function_eglCopyBuffers = 163,
+  Message_Function_eglGetError = 164,
+  Message_Function_eglQueryString = 165,
+  Message_Function_eglGetProcAddress = 166,
+  Message_Function_eglSurfaceAttrib = 167,
+  Message_Function_eglBindTexImage = 168,
+  Message_Function_eglReleaseTexImage = 169,
+  Message_Function_eglSwapInterval = 170,
+  Message_Function_eglBindAPI = 171,
+  Message_Function_eglQueryAPI = 172,
+  Message_Function_eglWaitClient = 173,
+  Message_Function_eglReleaseThread = 174,
+  Message_Function_eglCreatePbufferFromClientBuffer = 175,
+  Message_Function_eglLockSurfaceKHR = 176,
+  Message_Function_eglUnlockSurfaceKHR = 177,
+  Message_Function_eglCreateImageKHR = 178,
+  Message_Function_eglDestroyImageKHR = 179,
+  Message_Function_eglCreateSyncKHR = 180,
+  Message_Function_eglDestroySyncKHR = 181,
+  Message_Function_eglClientWaitSyncKHR = 182,
+  Message_Function_eglGetSyncAttribKHR = 183,
+  Message_Function_eglSetSwapRectangleANDROID = 184,
+  Message_Function_eglGetRenderBufferANDROID = 185,
+  Message_Function_ACK = 186,
+  Message_Function_NEG = 187,
+  Message_Function_CONTINUE = 188,
+  Message_Function_SKIP = 189,
+  Message_Function_SETPROP = 190,
+  Message_Function_CAPTURE = 191
+};
+bool Message_Function_IsValid(int value);
+const Message_Function Message_Function_Function_MIN = Message_Function_glActiveTexture;
+const Message_Function Message_Function_Function_MAX = Message_Function_CAPTURE;
+const int Message_Function_Function_ARRAYSIZE = Message_Function_Function_MAX + 1;
+
+enum Message_Type {
+  Message_Type_BeforeCall = 0,
+  Message_Type_AfterCall = 1,
+  Message_Type_Response = 2
+};
+bool Message_Type_IsValid(int value);
+const Message_Type Message_Type_Type_MIN = Message_Type_BeforeCall;
+const Message_Type Message_Type_Type_MAX = Message_Type_Response;
+const int Message_Type_Type_ARRAYSIZE = Message_Type_Type_MAX + 1;
+
+enum Message_Prop {
+  Message_Prop_Capture = 0,
+  Message_Prop_TimeMode = 1
+};
+bool Message_Prop_IsValid(int value);
+const Message_Prop Message_Prop_Prop_MIN = Message_Prop_Capture;
+const Message_Prop Message_Prop_Prop_MAX = Message_Prop_TimeMode;
+const int Message_Prop_Prop_ARRAYSIZE = Message_Prop_Prop_MAX + 1;
+
+// ===================================================================
+
+class Message : public ::google::protobuf::MessageLite {
+ public:
+  Message();
+  virtual ~Message();
+  
+  Message(const Message& from);
+  
+  inline Message& operator=(const Message& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  static const Message& default_instance();
+  
+  void Swap(Message* other);
+  
+  // implements Message ----------------------------------------------
+  
+  Message* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const Message& from);
+  void MergeFrom(const Message& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::std::string GetTypeName() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef Message_Function Function;
+  static const Function glActiveTexture = Message_Function_glActiveTexture;
+  static const Function glAttachShader = Message_Function_glAttachShader;
+  static const Function glBindAttribLocation = Message_Function_glBindAttribLocation;
+  static const Function glBindBuffer = Message_Function_glBindBuffer;
+  static const Function glBindFramebuffer = Message_Function_glBindFramebuffer;
+  static const Function glBindRenderbuffer = Message_Function_glBindRenderbuffer;
+  static const Function glBindTexture = Message_Function_glBindTexture;
+  static const Function glBlendColor = Message_Function_glBlendColor;
+  static const Function glBlendEquation = Message_Function_glBlendEquation;
+  static const Function glBlendEquationSeparate = Message_Function_glBlendEquationSeparate;
+  static const Function glBlendFunc = Message_Function_glBlendFunc;
+  static const Function glBlendFuncSeparate = Message_Function_glBlendFuncSeparate;
+  static const Function glBufferData = Message_Function_glBufferData;
+  static const Function glBufferSubData = Message_Function_glBufferSubData;
+  static const Function glCheckFramebufferStatus = Message_Function_glCheckFramebufferStatus;
+  static const Function glClear = Message_Function_glClear;
+  static const Function glClearColor = Message_Function_glClearColor;
+  static const Function glClearDepthf = Message_Function_glClearDepthf;
+  static const Function glClearStencil = Message_Function_glClearStencil;
+  static const Function glColorMask = Message_Function_glColorMask;
+  static const Function glCompileShader = Message_Function_glCompileShader;
+  static const Function glCompressedTexImage2D = Message_Function_glCompressedTexImage2D;
+  static const Function glCompressedTexSubImage2D = Message_Function_glCompressedTexSubImage2D;
+  static const Function glCopyTexImage2D = Message_Function_glCopyTexImage2D;
+  static const Function glCopyTexSubImage2D = Message_Function_glCopyTexSubImage2D;
+  static const Function glCreateProgram = Message_Function_glCreateProgram;
+  static const Function glCreateShader = Message_Function_glCreateShader;
+  static const Function glCullFace = Message_Function_glCullFace;
+  static const Function glDeleteBuffers = Message_Function_glDeleteBuffers;
+  static const Function glDeleteFramebuffers = Message_Function_glDeleteFramebuffers;
+  static const Function glDeleteProgram = Message_Function_glDeleteProgram;
+  static const Function glDeleteRenderbuffers = Message_Function_glDeleteRenderbuffers;
+  static const Function glDeleteShader = Message_Function_glDeleteShader;
+  static const Function glDeleteTextures = Message_Function_glDeleteTextures;
+  static const Function glDepthFunc = Message_Function_glDepthFunc;
+  static const Function glDepthMask = Message_Function_glDepthMask;
+  static const Function glDepthRangef = Message_Function_glDepthRangef;
+  static const Function glDetachShader = Message_Function_glDetachShader;
+  static const Function glDisable = Message_Function_glDisable;
+  static const Function glDisableVertexAttribArray = Message_Function_glDisableVertexAttribArray;
+  static const Function glDrawArrays = Message_Function_glDrawArrays;
+  static const Function glDrawElements = Message_Function_glDrawElements;
+  static const Function glEnable = Message_Function_glEnable;
+  static const Function glEnableVertexAttribArray = Message_Function_glEnableVertexAttribArray;
+  static const Function glFinish = Message_Function_glFinish;
+  static const Function glFlush = Message_Function_glFlush;
+  static const Function glFramebufferRenderbuffer = Message_Function_glFramebufferRenderbuffer;
+  static const Function glFramebufferTexture2D = Message_Function_glFramebufferTexture2D;
+  static const Function glFrontFace = Message_Function_glFrontFace;
+  static const Function glGenBuffers = Message_Function_glGenBuffers;
+  static const Function glGenerateMipmap = Message_Function_glGenerateMipmap;
+  static const Function glGenFramebuffers = Message_Function_glGenFramebuffers;
+  static const Function glGenRenderbuffers = Message_Function_glGenRenderbuffers;
+  static const Function glGenTextures = Message_Function_glGenTextures;
+  static const Function glGetActiveAttrib = Message_Function_glGetActiveAttrib;
+  static const Function glGetActiveUniform = Message_Function_glGetActiveUniform;
+  static const Function glGetAttachedShaders = Message_Function_glGetAttachedShaders;
+  static const Function glGetAttribLocation = Message_Function_glGetAttribLocation;
+  static const Function glGetBooleanv = Message_Function_glGetBooleanv;
+  static const Function glGetBufferParameteriv = Message_Function_glGetBufferParameteriv;
+  static const Function glGetError = Message_Function_glGetError;
+  static const Function glGetFloatv = Message_Function_glGetFloatv;
+  static const Function glGetFramebufferAttachmentParameteriv = Message_Function_glGetFramebufferAttachmentParameteriv;
+  static const Function glGetIntegerv = Message_Function_glGetIntegerv;
+  static const Function glGetProgramiv = Message_Function_glGetProgramiv;
+  static const Function glGetProgramInfoLog = Message_Function_glGetProgramInfoLog;
+  static const Function glGetRenderbufferParameteriv = Message_Function_glGetRenderbufferParameteriv;
+  static const Function glGetShaderiv = Message_Function_glGetShaderiv;
+  static const Function glGetShaderInfoLog = Message_Function_glGetShaderInfoLog;
+  static const Function glGetShaderPrecisionFormat = Message_Function_glGetShaderPrecisionFormat;
+  static const Function glGetShaderSource = Message_Function_glGetShaderSource;
+  static const Function glGetString = Message_Function_glGetString;
+  static const Function glGetTexParameterfv = Message_Function_glGetTexParameterfv;
+  static const Function glGetTexParameteriv = Message_Function_glGetTexParameteriv;
+  static const Function glGetUniformfv = Message_Function_glGetUniformfv;
+  static const Function glGetUniformiv = Message_Function_glGetUniformiv;
+  static const Function glGetUniformLocation = Message_Function_glGetUniformLocation;
+  static const Function glGetVertexAttribfv = Message_Function_glGetVertexAttribfv;
+  static const Function glGetVertexAttribiv = Message_Function_glGetVertexAttribiv;
+  static const Function glGetVertexAttribPointerv = Message_Function_glGetVertexAttribPointerv;
+  static const Function glHint = Message_Function_glHint;
+  static const Function glIsBuffer = Message_Function_glIsBuffer;
+  static const Function glIsEnabled = Message_Function_glIsEnabled;
+  static const Function glIsFramebuffer = Message_Function_glIsFramebuffer;
+  static const Function glIsProgram = Message_Function_glIsProgram;
+  static const Function glIsRenderbuffer = Message_Function_glIsRenderbuffer;
+  static const Function glIsShader = Message_Function_glIsShader;
+  static const Function glIsTexture = Message_Function_glIsTexture;
+  static const Function glLineWidth = Message_Function_glLineWidth;
+  static const Function glLinkProgram = Message_Function_glLinkProgram;
+  static const Function glPixelStorei = Message_Function_glPixelStorei;
+  static const Function glPolygonOffset = Message_Function_glPolygonOffset;
+  static const Function glReadPixels = Message_Function_glReadPixels;
+  static const Function glReleaseShaderCompiler = Message_Function_glReleaseShaderCompiler;
+  static const Function glRenderbufferStorage = Message_Function_glRenderbufferStorage;
+  static const Function glSampleCoverage = Message_Function_glSampleCoverage;
+  static const Function glScissor = Message_Function_glScissor;
+  static const Function glShaderBinary = Message_Function_glShaderBinary;
+  static const Function glShaderSource = Message_Function_glShaderSource;
+  static const Function glStencilFunc = Message_Function_glStencilFunc;
+  static const Function glStencilFuncSeparate = Message_Function_glStencilFuncSeparate;
+  static const Function glStencilMask = Message_Function_glStencilMask;
+  static const Function glStencilMaskSeparate = Message_Function_glStencilMaskSeparate;
+  static const Function glStencilOp = Message_Function_glStencilOp;
+  static const Function glStencilOpSeparate = Message_Function_glStencilOpSeparate;
+  static const Function glTexImage2D = Message_Function_glTexImage2D;
+  static const Function glTexParameterf = Message_Function_glTexParameterf;
+  static const Function glTexParameterfv = Message_Function_glTexParameterfv;
+  static const Function glTexParameteri = Message_Function_glTexParameteri;
+  static const Function glTexParameteriv = Message_Function_glTexParameteriv;
+  static const Function glTexSubImage2D = Message_Function_glTexSubImage2D;
+  static const Function glUniform1f = Message_Function_glUniform1f;
+  static const Function glUniform1fv = Message_Function_glUniform1fv;
+  static const Function glUniform1i = Message_Function_glUniform1i;
+  static const Function glUniform1iv = Message_Function_glUniform1iv;
+  static const Function glUniform2f = Message_Function_glUniform2f;
+  static const Function glUniform2fv = Message_Function_glUniform2fv;
+  static const Function glUniform2i = Message_Function_glUniform2i;
+  static const Function glUniform2iv = Message_Function_glUniform2iv;
+  static const Function glUniform3f = Message_Function_glUniform3f;
+  static const Function glUniform3fv = Message_Function_glUniform3fv;
+  static const Function glUniform3i = Message_Function_glUniform3i;
+  static const Function glUniform3iv = Message_Function_glUniform3iv;
+  static const Function glUniform4f = Message_Function_glUniform4f;
+  static const Function glUniform4fv = Message_Function_glUniform4fv;
+  static const Function glUniform4i = Message_Function_glUniform4i;
+  static const Function glUniform4iv = Message_Function_glUniform4iv;
+  static const Function glUniformMatrix2fv = Message_Function_glUniformMatrix2fv;
+  static const Function glUniformMatrix3fv = Message_Function_glUniformMatrix3fv;
+  static const Function glUniformMatrix4fv = Message_Function_glUniformMatrix4fv;
+  static const Function glUseProgram = Message_Function_glUseProgram;
+  static const Function glValidateProgram = Message_Function_glValidateProgram;
+  static const Function glVertexAttrib1f = Message_Function_glVertexAttrib1f;
+  static const Function glVertexAttrib1fv = Message_Function_glVertexAttrib1fv;
+  static const Function glVertexAttrib2f = Message_Function_glVertexAttrib2f;
+  static const Function glVertexAttrib2fv = Message_Function_glVertexAttrib2fv;
+  static const Function glVertexAttrib3f = Message_Function_glVertexAttrib3f;
+  static const Function glVertexAttrib3fv = Message_Function_glVertexAttrib3fv;
+  static const Function glVertexAttrib4f = Message_Function_glVertexAttrib4f;
+  static const Function glVertexAttrib4fv = Message_Function_glVertexAttrib4fv;
+  static const Function glVertexAttribPointer = Message_Function_glVertexAttribPointer;
+  static const Function glViewport = Message_Function_glViewport;
+  static const Function eglGetDisplay = Message_Function_eglGetDisplay;
+  static const Function eglInitialize = Message_Function_eglInitialize;
+  static const Function eglTerminate = Message_Function_eglTerminate;
+  static const Function eglGetConfigs = Message_Function_eglGetConfigs;
+  static const Function eglChooseConfig = Message_Function_eglChooseConfig;
+  static const Function eglGetConfigAttrib = Message_Function_eglGetConfigAttrib;
+  static const Function eglCreateWindowSurface = Message_Function_eglCreateWindowSurface;
+  static const Function eglCreatePixmapSurface = Message_Function_eglCreatePixmapSurface;
+  static const Function eglCreatePbufferSurface = Message_Function_eglCreatePbufferSurface;
+  static const Function eglDestroySurface = Message_Function_eglDestroySurface;
+  static const Function eglQuerySurface = Message_Function_eglQuerySurface;
+  static const Function eglCreateContext = Message_Function_eglCreateContext;
+  static const Function eglDestroyContext = Message_Function_eglDestroyContext;
+  static const Function eglMakeCurrent = Message_Function_eglMakeCurrent;
+  static const Function eglGetCurrentContext = Message_Function_eglGetCurrentContext;
+  static const Function eglGetCurrentSurface = Message_Function_eglGetCurrentSurface;
+  static const Function eglGetCurrentDisplay = Message_Function_eglGetCurrentDisplay;
+  static const Function eglQueryContext = Message_Function_eglQueryContext;
+  static const Function eglWaitGL = Message_Function_eglWaitGL;
+  static const Function eglWaitNative = Message_Function_eglWaitNative;
+  static const Function eglSwapBuffers = Message_Function_eglSwapBuffers;
+  static const Function eglCopyBuffers = Message_Function_eglCopyBuffers;
+  static const Function eglGetError = Message_Function_eglGetError;
+  static const Function eglQueryString = Message_Function_eglQueryString;
+  static const Function eglGetProcAddress = Message_Function_eglGetProcAddress;
+  static const Function eglSurfaceAttrib = Message_Function_eglSurfaceAttrib;
+  static const Function eglBindTexImage = Message_Function_eglBindTexImage;
+  static const Function eglReleaseTexImage = Message_Function_eglReleaseTexImage;
+  static const Function eglSwapInterval = Message_Function_eglSwapInterval;
+  static const Function eglBindAPI = Message_Function_eglBindAPI;
+  static const Function eglQueryAPI = Message_Function_eglQueryAPI;
+  static const Function eglWaitClient = Message_Function_eglWaitClient;
+  static const Function eglReleaseThread = Message_Function_eglReleaseThread;
+  static const Function eglCreatePbufferFromClientBuffer = Message_Function_eglCreatePbufferFromClientBuffer;
+  static const Function eglLockSurfaceKHR = Message_Function_eglLockSurfaceKHR;
+  static const Function eglUnlockSurfaceKHR = Message_Function_eglUnlockSurfaceKHR;
+  static const Function eglCreateImageKHR = Message_Function_eglCreateImageKHR;
+  static const Function eglDestroyImageKHR = Message_Function_eglDestroyImageKHR;
+  static const Function eglCreateSyncKHR = Message_Function_eglCreateSyncKHR;
+  static const Function eglDestroySyncKHR = Message_Function_eglDestroySyncKHR;
+  static const Function eglClientWaitSyncKHR = Message_Function_eglClientWaitSyncKHR;
+  static const Function eglGetSyncAttribKHR = Message_Function_eglGetSyncAttribKHR;
+  static const Function eglSetSwapRectangleANDROID = Message_Function_eglSetSwapRectangleANDROID;
+  static const Function eglGetRenderBufferANDROID = Message_Function_eglGetRenderBufferANDROID;
+  static const Function ACK = Message_Function_ACK;
+  static const Function NEG = Message_Function_NEG;
+  static const Function CONTINUE = Message_Function_CONTINUE;
+  static const Function SKIP = Message_Function_SKIP;
+  static const Function SETPROP = Message_Function_SETPROP;
+  static const Function CAPTURE = Message_Function_CAPTURE;
+  static inline bool Function_IsValid(int value) {
+    return Message_Function_IsValid(value);
+  }
+  static const Function Function_MIN =
+    Message_Function_Function_MIN;
+  static const Function Function_MAX =
+    Message_Function_Function_MAX;
+  static const int Function_ARRAYSIZE =
+    Message_Function_Function_ARRAYSIZE;
+  
+  typedef Message_Type Type;
+  static const Type BeforeCall = Message_Type_BeforeCall;
+  static const Type AfterCall = Message_Type_AfterCall;
+  static const Type Response = Message_Type_Response;
+  static inline bool Type_IsValid(int value) {
+    return Message_Type_IsValid(value);
+  }
+  static const Type Type_MIN =
+    Message_Type_Type_MIN;
+  static const Type Type_MAX =
+    Message_Type_Type_MAX;
+  static const int Type_ARRAYSIZE =
+    Message_Type_Type_ARRAYSIZE;
+  
+  typedef Message_Prop Prop;
+  static const Prop Capture = Message_Prop_Capture;
+  static const Prop TimeMode = Message_Prop_TimeMode;
+  static inline bool Prop_IsValid(int value) {
+    return Message_Prop_IsValid(value);
+  }
+  static const Prop Prop_MIN =
+    Message_Prop_Prop_MIN;
+  static const Prop Prop_MAX =
+    Message_Prop_Prop_MAX;
+  static const int Prop_ARRAYSIZE =
+    Message_Prop_Prop_ARRAYSIZE;
+  
+  // accessors -------------------------------------------------------
+  
+  // required int32 context_id = 1;
+  inline bool has_context_id() const;
+  inline void clear_context_id();
+  static const int kContextIdFieldNumber = 1;
+  inline ::google::protobuf::int32 context_id() const;
+  inline void set_context_id(::google::protobuf::int32 value);
+  
+  // required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+  inline bool has_function() const;
+  inline void clear_function();
+  static const int kFunctionFieldNumber = 2;
+  inline ::com::android::glesv2debugger::Message_Function function() const;
+  inline void set_function(::com::android::glesv2debugger::Message_Function value);
+  
+  // required .com.android.glesv2debugger.Message.Type type = 3;
+  inline bool has_type() const;
+  inline void clear_type();
+  static const int kTypeFieldNumber = 3;
+  inline ::com::android::glesv2debugger::Message_Type type() const;
+  inline void set_type(::com::android::glesv2debugger::Message_Type value);
+  
+  // required bool expect_response = 4;
+  inline bool has_expect_response() const;
+  inline void clear_expect_response();
+  static const int kExpectResponseFieldNumber = 4;
+  inline bool expect_response() const;
+  inline void set_expect_response(bool value);
+  
+  // optional int32 ret = 5;
+  inline bool has_ret() const;
+  inline void clear_ret();
+  static const int kRetFieldNumber = 5;
+  inline ::google::protobuf::int32 ret() const;
+  inline void set_ret(::google::protobuf::int32 value);
+  
+  // optional int32 arg0 = 6;
+  inline bool has_arg0() const;
+  inline void clear_arg0();
+  static const int kArg0FieldNumber = 6;
+  inline ::google::protobuf::int32 arg0() const;
+  inline void set_arg0(::google::protobuf::int32 value);
+  
+  // optional int32 arg1 = 7;
+  inline bool has_arg1() const;
+  inline void clear_arg1();
+  static const int kArg1FieldNumber = 7;
+  inline ::google::protobuf::int32 arg1() const;
+  inline void set_arg1(::google::protobuf::int32 value);
+  
+  // optional int32 arg2 = 8;
+  inline bool has_arg2() const;
+  inline void clear_arg2();
+  static const int kArg2FieldNumber = 8;
+  inline ::google::protobuf::int32 arg2() const;
+  inline void set_arg2(::google::protobuf::int32 value);
+  
+  // optional int32 arg3 = 9;
+  inline bool has_arg3() const;
+  inline void clear_arg3();
+  static const int kArg3FieldNumber = 9;
+  inline ::google::protobuf::int32 arg3() const;
+  inline void set_arg3(::google::protobuf::int32 value);
+  
+  // optional int32 arg4 = 16;
+  inline bool has_arg4() const;
+  inline void clear_arg4();
+  static const int kArg4FieldNumber = 16;
+  inline ::google::protobuf::int32 arg4() const;
+  inline void set_arg4(::google::protobuf::int32 value);
+  
+  // optional int32 arg5 = 17;
+  inline bool has_arg5() const;
+  inline void clear_arg5();
+  static const int kArg5FieldNumber = 17;
+  inline ::google::protobuf::int32 arg5() const;
+  inline void set_arg5(::google::protobuf::int32 value);
+  
+  // optional int32 arg6 = 18;
+  inline bool has_arg6() const;
+  inline void clear_arg6();
+  static const int kArg6FieldNumber = 18;
+  inline ::google::protobuf::int32 arg6() const;
+  inline void set_arg6(::google::protobuf::int32 value);
+  
+  // optional int32 arg7 = 19;
+  inline bool has_arg7() const;
+  inline void clear_arg7();
+  static const int kArg7FieldNumber = 19;
+  inline ::google::protobuf::int32 arg7() const;
+  inline void set_arg7(::google::protobuf::int32 value);
+  
+  // optional int32 arg8 = 20;
+  inline bool has_arg8() const;
+  inline void clear_arg8();
+  static const int kArg8FieldNumber = 20;
+  inline ::google::protobuf::int32 arg8() const;
+  inline void set_arg8(::google::protobuf::int32 value);
+  
+  // optional bytes data = 10;
+  inline bool has_data() const;
+  inline void clear_data();
+  static const int kDataFieldNumber = 10;
+  inline const ::std::string& data() const;
+  inline void set_data(const ::std::string& value);
+  inline void set_data(const char* value);
+  inline void set_data(const void* value, size_t size);
+  inline ::std::string* mutable_data();
+  
+  // optional float time = 11;
+  inline bool has_time() const;
+  inline void clear_time();
+  static const int kTimeFieldNumber = 11;
+  inline float time() const;
+  inline void set_time(float value);
+  
+  // optional .com.android.glesv2debugger.Message.Prop prop = 21;
+  inline bool has_prop() const;
+  inline void clear_prop();
+  static const int kPropFieldNumber = 21;
+  inline ::com::android::glesv2debugger::Message_Prop prop() const;
+  inline void set_prop(::com::android::glesv2debugger::Message_Prop value);
+  
+  // optional float clock = 22;
+  inline bool has_clock() const;
+  inline void clear_clock();
+  static const int kClockFieldNumber = 22;
+  inline float clock() const;
+  inline void set_clock(float value);
+  
+  // @@protoc_insertion_point(class_scope:com.android.glesv2debugger.Message)
+ private:
+  mutable int _cached_size_;
+  
+  ::google::protobuf::int32 context_id_;
+  int function_;
+  int type_;
+  bool expect_response_;
+  ::google::protobuf::int32 ret_;
+  ::google::protobuf::int32 arg0_;
+  ::google::protobuf::int32 arg1_;
+  ::google::protobuf::int32 arg2_;
+  ::google::protobuf::int32 arg3_;
+  ::google::protobuf::int32 arg4_;
+  ::google::protobuf::int32 arg5_;
+  ::google::protobuf::int32 arg6_;
+  ::google::protobuf::int32 arg7_;
+  ::google::protobuf::int32 arg8_;
+  ::std::string* data_;
+  static const ::std::string _default_data_;
+  float time_;
+  int prop_;
+  float clock_;
+  friend void  protobuf_AddDesc_debugger_5fmessage_2eproto();
+  friend void protobuf_AssignDesc_debugger_5fmessage_2eproto();
+  friend void protobuf_ShutdownFile_debugger_5fmessage_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(18 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static Message* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+// Message
+
+// required int32 context_id = 1;
+inline bool Message::has_context_id() const {
+  return _has_bit(0);
+}
+inline void Message::clear_context_id() {
+  context_id_ = 0;
+  _clear_bit(0);
+}
+inline ::google::protobuf::int32 Message::context_id() const {
+  return context_id_;
+}
+inline void Message::set_context_id(::google::protobuf::int32 value) {
+  _set_bit(0);
+  context_id_ = value;
+}
+
+// required .com.android.glesv2debugger.Message.Function function = 2 [default = NEG];
+inline bool Message::has_function() const {
+  return _has_bit(1);
+}
+inline void Message::clear_function() {
+  function_ = 187;
+  _clear_bit(1);
+}
+inline ::com::android::glesv2debugger::Message_Function Message::function() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Function >(function_);
+}
+inline void Message::set_function(::com::android::glesv2debugger::Message_Function value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Function_IsValid(value));
+  _set_bit(1);
+  function_ = value;
+}
+
+// required .com.android.glesv2debugger.Message.Type type = 3;
+inline bool Message::has_type() const {
+  return _has_bit(2);
+}
+inline void Message::clear_type() {
+  type_ = 0;
+  _clear_bit(2);
+}
+inline ::com::android::glesv2debugger::Message_Type Message::type() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Type >(type_);
+}
+inline void Message::set_type(::com::android::glesv2debugger::Message_Type value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Type_IsValid(value));
+  _set_bit(2);
+  type_ = value;
+}
+
+// required bool expect_response = 4;
+inline bool Message::has_expect_response() const {
+  return _has_bit(3);
+}
+inline void Message::clear_expect_response() {
+  expect_response_ = false;
+  _clear_bit(3);
+}
+inline bool Message::expect_response() const {
+  return expect_response_;
+}
+inline void Message::set_expect_response(bool value) {
+  _set_bit(3);
+  expect_response_ = value;
+}
+
+// optional int32 ret = 5;
+inline bool Message::has_ret() const {
+  return _has_bit(4);
+}
+inline void Message::clear_ret() {
+  ret_ = 0;
+  _clear_bit(4);
+}
+inline ::google::protobuf::int32 Message::ret() const {
+  return ret_;
+}
+inline void Message::set_ret(::google::protobuf::int32 value) {
+  _set_bit(4);
+  ret_ = value;
+}
+
+// optional int32 arg0 = 6;
+inline bool Message::has_arg0() const {
+  return _has_bit(5);
+}
+inline void Message::clear_arg0() {
+  arg0_ = 0;
+  _clear_bit(5);
+}
+inline ::google::protobuf::int32 Message::arg0() const {
+  return arg0_;
+}
+inline void Message::set_arg0(::google::protobuf::int32 value) {
+  _set_bit(5);
+  arg0_ = value;
+}
+
+// optional int32 arg1 = 7;
+inline bool Message::has_arg1() const {
+  return _has_bit(6);
+}
+inline void Message::clear_arg1() {
+  arg1_ = 0;
+  _clear_bit(6);
+}
+inline ::google::protobuf::int32 Message::arg1() const {
+  return arg1_;
+}
+inline void Message::set_arg1(::google::protobuf::int32 value) {
+  _set_bit(6);
+  arg1_ = value;
+}
+
+// optional int32 arg2 = 8;
+inline bool Message::has_arg2() const {
+  return _has_bit(7);
+}
+inline void Message::clear_arg2() {
+  arg2_ = 0;
+  _clear_bit(7);
+}
+inline ::google::protobuf::int32 Message::arg2() const {
+  return arg2_;
+}
+inline void Message::set_arg2(::google::protobuf::int32 value) {
+  _set_bit(7);
+  arg2_ = value;
+}
+
+// optional int32 arg3 = 9;
+inline bool Message::has_arg3() const {
+  return _has_bit(8);
+}
+inline void Message::clear_arg3() {
+  arg3_ = 0;
+  _clear_bit(8);
+}
+inline ::google::protobuf::int32 Message::arg3() const {
+  return arg3_;
+}
+inline void Message::set_arg3(::google::protobuf::int32 value) {
+  _set_bit(8);
+  arg3_ = value;
+}
+
+// optional int32 arg4 = 16;
+inline bool Message::has_arg4() const {
+  return _has_bit(9);
+}
+inline void Message::clear_arg4() {
+  arg4_ = 0;
+  _clear_bit(9);
+}
+inline ::google::protobuf::int32 Message::arg4() const {
+  return arg4_;
+}
+inline void Message::set_arg4(::google::protobuf::int32 value) {
+  _set_bit(9);
+  arg4_ = value;
+}
+
+// optional int32 arg5 = 17;
+inline bool Message::has_arg5() const {
+  return _has_bit(10);
+}
+inline void Message::clear_arg5() {
+  arg5_ = 0;
+  _clear_bit(10);
+}
+inline ::google::protobuf::int32 Message::arg5() const {
+  return arg5_;
+}
+inline void Message::set_arg5(::google::protobuf::int32 value) {
+  _set_bit(10);
+  arg5_ = value;
+}
+
+// optional int32 arg6 = 18;
+inline bool Message::has_arg6() const {
+  return _has_bit(11);
+}
+inline void Message::clear_arg6() {
+  arg6_ = 0;
+  _clear_bit(11);
+}
+inline ::google::protobuf::int32 Message::arg6() const {
+  return arg6_;
+}
+inline void Message::set_arg6(::google::protobuf::int32 value) {
+  _set_bit(11);
+  arg6_ = value;
+}
+
+// optional int32 arg7 = 19;
+inline bool Message::has_arg7() const {
+  return _has_bit(12);
+}
+inline void Message::clear_arg7() {
+  arg7_ = 0;
+  _clear_bit(12);
+}
+inline ::google::protobuf::int32 Message::arg7() const {
+  return arg7_;
+}
+inline void Message::set_arg7(::google::protobuf::int32 value) {
+  _set_bit(12);
+  arg7_ = value;
+}
+
+// optional int32 arg8 = 20;
+inline bool Message::has_arg8() const {
+  return _has_bit(13);
+}
+inline void Message::clear_arg8() {
+  arg8_ = 0;
+  _clear_bit(13);
+}
+inline ::google::protobuf::int32 Message::arg8() const {
+  return arg8_;
+}
+inline void Message::set_arg8(::google::protobuf::int32 value) {
+  _set_bit(13);
+  arg8_ = value;
+}
+
+// optional bytes data = 10;
+inline bool Message::has_data() const {
+  return _has_bit(14);
+}
+inline void Message::clear_data() {
+  if (data_ != &_default_data_) {
+    data_->clear();
+  }
+  _clear_bit(14);
+}
+inline const ::std::string& Message::data() const {
+  return *data_;
+}
+inline void Message::set_data(const ::std::string& value) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Message::set_data(const char* value) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Message::set_data(const void* value, size_t size) {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* Message::mutable_data() {
+  _set_bit(14);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  return data_;
+}
+
+// optional float time = 11;
+inline bool Message::has_time() const {
+  return _has_bit(15);
+}
+inline void Message::clear_time() {
+  time_ = 0;
+  _clear_bit(15);
+}
+inline float Message::time() const {
+  return time_;
+}
+inline void Message::set_time(float value) {
+  _set_bit(15);
+  time_ = value;
+}
+
+// optional .com.android.glesv2debugger.Message.Prop prop = 21;
+inline bool Message::has_prop() const {
+  return _has_bit(16);
+}
+inline void Message::clear_prop() {
+  prop_ = 0;
+  _clear_bit(16);
+}
+inline ::com::android::glesv2debugger::Message_Prop Message::prop() const {
+  return static_cast< ::com::android::glesv2debugger::Message_Prop >(prop_);
+}
+inline void Message::set_prop(::com::android::glesv2debugger::Message_Prop value) {
+  GOOGLE_DCHECK(::com::android::glesv2debugger::Message_Prop_IsValid(value));
+  _set_bit(16);
+  prop_ = value;
+}
+
+// optional float clock = 22;
+inline bool Message::has_clock() const {
+  return _has_bit(17);
+}
+inline void Message::clear_clock() {
+  clock_ = 0;
+  _clear_bit(17);
+}
+inline float Message::clock() const {
+  return clock_;
+}
+inline void Message::set_clock(float value) {
+  _set_bit(17);
+  clock_ = value;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace glesv2debugger
+}  // namespace android
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_debugger_5fmessage_2eproto__INCLUDED
diff --git a/opengl/libs/GLES2_dbg/src/egl.cpp b/opengl/libs/GLES2_dbg/src/egl.cpp
new file mode 100644
index 0000000..b3979a3
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/egl.cpp
@@ -0,0 +1,41 @@
+/*
+ ** 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 "header.h"
+
+EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = true;
+    struct : public FunctionCall {
+        EGLDisplay dpy;
+        EGLSurface draw;
+        
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            msg.set_time(-1);
+            return reinterpret_cast<const int *>(true);
+        }
+    } caller;
+    caller.dpy = dpy;
+    caller.draw = draw;
+    
+    msg.set_arg0(reinterpret_cast<int>(dpy));
+    msg.set_arg1(reinterpret_cast<int>(draw));
+    
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_eglSwapBuffers);
+    return static_cast<EGLBoolean>(reinterpret_cast<int>(ret));
+}
diff --git a/opengl/libs/GLES2_dbg/src/header.h b/opengl/libs/GLES2_dbg/src/header.h
new file mode 100644
index 0000000..cbd448a
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/header.h
@@ -0,0 +1,129 @@
+/*
+ ** 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 <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <cutils/log.h>
+#include <utils/Timers.h>
+#include <../../../libcore/include/StaticAssert.h>
+
+#define EGL_TRACE 1
+#include "hooks.h"
+
+#include "glesv2dbg.h"
+
+#define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
+#include "glesv2dbg_functions.h"
+
+#include "debugger_message.pb.h"
+
+using namespace android;
+using namespace com::android;
+
+#define API_ENTRY(_api) Debug_##_api
+
+#ifndef __location__
+#define __HIERALLOC_STRING_0__(s)   #s
+#define __HIERALLOC_STRING_1__(s)   __HIERALLOC_STRING_0__(s)
+#define __HIERALLOC_STRING_2__      __HIERALLOC_STRING_1__(__LINE__)
+#define __location__                __FILE__ ":" __HIERALLOC_STRING_2__
+#endif
+
+#undef assert
+#define assert(expr) if (!(expr)) { LOGD("\n*\n*\n* assert: %s at %s \n*\n*", #expr, __location__); int * x = 0; *x = 5; }
+//#undef LOGD
+//#define LOGD(...)
+
+namespace android
+{
+
+struct DbgContext {
+    const unsigned version; // 0 is GLES1, 1 is GLES2
+    const gl_hooks_t * const hooks;
+    const unsigned MAX_VERTEX_ATTRIBS;
+    
+    struct VertexAttrib {
+        GLenum type; // element data type
+        unsigned size; // number of data per element
+        unsigned stride; // calculated number of bytes between elements
+        const void * ptr;
+        unsigned elemSize; // calculated number of bytes per element
+        GLuint buffer; // buffer name
+        GLboolean normalized : 1;
+        GLboolean enabled : 1;
+        VertexAttrib() : type(0), size(0), stride(0), ptr(NULL), elemSize(0),
+                buffer(0), normalized(0), enabled(0) {}
+    } * vertexAttribs;
+    bool hasNonVBOAttribs; // whether any enabled vertexAttrib is user pointer
+
+    struct VBO {
+        const GLuint name;
+        const GLenum target;
+        VBO * next;
+        void * data; // malloc/free
+        unsigned size; // in bytes
+        VBO(const GLuint name, const GLenum target, VBO * head) : name(name),
+                target(target), next(head), data(NULL), size(0) {}
+    } * indexBuffers; // linked list of all index buffers
+    VBO * indexBuffer; // currently bound index buffer
+
+    GLuint program;
+    unsigned maxAttrib; // number of slots used by program
+
+    DbgContext(const unsigned version, const gl_hooks_t * const hooks, const unsigned MAX_VERTEX_ATTRIBS);
+    ~DbgContext();
+
+    void Fetch(const unsigned index, std::string * const data) const;
+
+    void glUseProgram(GLuint program);
+    void glEnableVertexAttribArray(GLuint index);
+    void glDisableVertexAttribArray(GLuint index);
+    void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+    void glBindBuffer(GLenum target, GLuint buffer);
+    void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+    void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+    void glDeleteBuffers(GLsizei n, const GLuint *buffers);
+};
+
+
+DbgContext * getDbgContextThreadSpecific();
+#define DBGCONTEXT(ctx) DbgContext * const ctx = getDbgContextThreadSpecific();
+
+struct FunctionCall {
+    virtual const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) = 0;
+    virtual ~FunctionCall() {}
+};
+
+// move these into DbgContext
+extern bool capture;
+extern int timeMode; // SYSTEM_TIME_
+
+extern int clientSock, serverSock;
+
+unsigned GetBytesPerPixel(const GLenum format, const GLenum type);
+
+int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
+                  const bool expectResponse, const glesv2debugger::Message_Function function);
+void Receive(glesv2debugger::Message & cmd);
+float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd);
+void SetProp(const glesv2debugger::Message & cmd);
+}; // namespace android {
diff --git a/opengl/libs/GLES2_dbg/src/server.cpp b/opengl/libs/GLES2_dbg/src/server.cpp
new file mode 100644
index 0000000..820e9de
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/server.cpp
@@ -0,0 +1,228 @@
+/*
+ ** 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 <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+
+#include "header.h"
+
+namespace android
+{
+
+int serverSock = -1, clientSock = -1;
+
+int timeMode = SYSTEM_TIME_THREAD;
+
+static void Die(const char * msg)
+{
+    LOGD("\n*\n*\n* GLESv2_dbg: Die: %s \n*\n*", msg);
+    StopDebugServer();
+    exit(1);
+}
+
+void StartDebugServer()
+{
+    LOGD("GLESv2_dbg: StartDebugServer");
+    if (serverSock >= 0)
+        return;
+
+    LOGD("GLESv2_dbg: StartDebugServer create socket");
+    struct sockaddr_in server = {}, client = {};
+
+    /* Create the TCP socket */
+    if ((serverSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+        Die("Failed to create socket");
+    }
+    /* Construct the server sockaddr_in structure */
+    server.sin_family = AF_INET;                  /* Internet/IP */
+    server.sin_addr.s_addr = htonl(INADDR_ANY);   /* Incoming addr */
+    server.sin_port = htons(5039);       /* server port */
+
+    /* Bind the server socket */
+    socklen_t sizeofSockaddr_in = sizeof(sockaddr_in);
+    if (bind(serverSock, (struct sockaddr *) &server,
+             sizeof(server)) < 0) {
+        Die("Failed to bind the server socket");
+    }
+    /* Listen on the server socket */
+    if (listen(serverSock, 1) < 0) {
+        Die("Failed to listen on server socket");
+    }
+
+    LOGD("server started on %d \n", server.sin_port);
+
+
+    /* Wait for client connection */
+    if ((clientSock =
+                accept(serverSock, (struct sockaddr *) &client,
+                       &sizeofSockaddr_in)) < 0) {
+        Die("Failed to accept client connection");
+    }
+
+    LOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
+//    fcntl(clientSock, F_SETFL, O_NONBLOCK);
+
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(0);
+    msg.set_function(glesv2debugger::Message_Function_ACK);
+    msg.set_type(glesv2debugger::Message_Type_Response);
+    msg.set_expect_response(false);
+    Send(msg, cmd);
+}
+
+void StopDebugServer()
+{
+    LOGD("GLESv2_dbg: StopDebugServer");
+    if (clientSock > 0) {
+        close(clientSock);
+        clientSock = -1;
+    }
+    if (serverSock > 0) {
+        close(serverSock);
+        serverSock = -1;
+    }
+
+}
+
+void Receive(glesv2debugger::Message & cmd)
+{
+    unsigned len = 0;
+
+    int received = recv(clientSock, &len, 4, MSG_WAITALL);
+    if (received < 0)
+        Die("Failed to receive response length");
+    else if (4 != received) {
+        LOGD("received %dB: %.8X", received, len);
+        Die("Received length mismatch, expected 4");
+    }
+    len = ntohl(len);
+    static void * buffer = NULL;
+    static unsigned bufferSize = 0;
+    if (bufferSize < len) {
+        buffer = realloc(buffer, len);
+        assert(buffer);
+        bufferSize = len;
+    }
+    received = recv(clientSock, buffer, len, MSG_WAITALL);
+    if (received < 0)
+        Die("Failed to receive response");
+    else if (len != received)
+        Die("Received length mismatch");
+    cmd.Clear();
+    cmd.ParseFromArray(buffer, len);
+}
+
+float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
+{
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutex_lock(&mutex); // TODO: this is just temporary
+
+    if (msg.function() != glesv2debugger::Message_Function_ACK)
+        assert(msg.has_context_id() && msg.context_id() != 0);
+    static std::string str;
+    msg.SerializeToString(&str);
+    unsigned len = str.length();
+    len = htonl(len);
+    int sent = -1;
+    sent = send(clientSock, (const char *)&len, sizeof(len), 0);
+    if (sent != sizeof(len)) {
+        LOGD("actual sent=%d expected=%d clientSock=%d", sent, sizeof(len), clientSock);
+        Die("Failed to send message length");
+    }
+    nsecs_t c0 = systemTime(timeMode);
+    sent = send(clientSock, str.c_str(), str.length(), 0);
+    float t = (float)ns2ms(systemTime(timeMode) - c0);
+    if (sent != str.length()) {
+        LOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
+        Die("Failed to send message");
+    }
+
+    if (!msg.expect_response()) {
+        pthread_mutex_unlock(&mutex);
+        return t;
+    }
+
+    Receive(cmd);
+
+    //LOGD("Message sent tid=%lu len=%d", pthread_self(), str.length());
+    pthread_mutex_unlock(&mutex);
+    return t;
+}
+
+void SetProp(const glesv2debugger::Message & cmd)
+{
+    switch (cmd.prop()) {
+    case glesv2debugger::Message_Prop_Capture:
+        LOGD("SetProp Message_Prop_Capture %d", cmd.arg0());
+        capture = cmd.arg0();
+        break;
+    case glesv2debugger::Message_Prop_TimeMode:
+        LOGD("SetProp Message_Prop_TimeMode %d", cmd.arg0());
+        timeMode = cmd.arg0();
+        break;
+    default:
+        assert(0);
+    }
+}
+
+int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
+                  const bool expectResponse, const glesv2debugger::Message_Function function)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    const int * ret = 0;
+    glesv2debugger::Message cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    msg.set_expect_response(expectResponse);
+    msg.set_function(function);
+    Send(msg, cmd);
+    if (!expectResponse)
+        cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            ret = functionCall(&dbg->hooks->gl, msg);
+            if (!msg.has_time()) // some has output data copy, so time inside call
+                msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(function);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            Send(msg, cmd);
+            if (!expectResponse)
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return const_cast<int *>(ret);
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(cmd);
+            Receive(cmd);
+            break;
+        default:
+            assert(0); //GenerateCall(msg, cmd);
+            break;
+        }
+    }
+    return 0;
+}
+}; // namespace android {
diff --git a/opengl/libs/GLES2_dbg/src/texture.cpp b/opengl/libs/GLES2_dbg/src/texture.cpp
new file mode 100644
index 0000000..3aa0aab
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/texture.cpp
@@ -0,0 +1,265 @@
+/*
+ ** 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 "header.h"
+
+namespace android
+{
+unsigned GetBytesPerPixel(const GLenum format, const GLenum type)
+{
+    switch (type) {
+    case GL_UNSIGNED_SHORT_5_6_5:
+        return 2;
+    case GL_UNSIGNED_SHORT_4_4_4_4:
+        return 2;
+    case GL_UNSIGNED_SHORT_5_5_5_1:
+        return 2;
+    case GL_UNSIGNED_BYTE:
+        break;
+    default:
+        assert(0);
+    }
+
+    switch (format) {
+    case GL_ALPHA:
+        return 1;
+    case GL_LUMINANCE:
+        return 1;
+        break;
+    case GL_LUMINANCE_ALPHA:
+        return 2;
+    case GL_RGB:
+        return 3;
+    case GL_RGBA:
+        return 4;
+    default:
+        assert(0);
+        return 0;
+    }
+}
+
+#define USE_RLE 0
+#if USE_RLE
+export template<typename T>
+void * RLEEncode(const void * pixels, unsigned count, unsigned * encodedSize)
+{
+    // first is a byte indicating data size [1,2,4] bytes
+    // then an unsigned indicating decompressed size
+    // then a byte of header: MSB == 1 indicates run, else literal
+    // LSB7 is run or literal length (actual length - 1)
+
+    const T * data = (T *)pixels;
+    unsigned bufferSize = sizeof(T) * count / 2 + 8;
+    unsigned char * buffer = (unsigned char *)malloc(bufferSize);
+    buffer[0] = sizeof(T);
+    unsigned bufferWritten = 1; // number of bytes written
+    *(unsigned *)(buffer + bufferWritten) = count;
+    bufferWritten += sizeof(count);
+    while (count) {
+        unsigned char run = 1;
+        bool repeat = true;
+        for (run = 1; run < count; run++)
+            if (data[0] != data[run]) {
+                repeat = false;
+                break;
+            } else if (run > 126)
+                break;
+        if (!repeat) {
+            // find literal length
+            for (run = 1; run < count; run++)
+                if (data[run - 1] == data[run])
+                    break;
+                else if (run > 126)
+                    break;
+            unsigned bytesToWrite = 1 + sizeof(T) * run;
+            if (bufferWritten + bytesToWrite > bufferSize) {
+                bufferSize += sizeof(T) * run + 256;
+                buffer = (unsigned char *)realloc(buffer, bufferSize);
+            }
+            buffer[bufferWritten++] = run - 1;
+            for (unsigned i = 0; i < run; i++) {
+                *(T *)(buffer + bufferWritten) = *data;
+                bufferWritten += sizeof(T);
+                data++;
+            }
+            count -= run;
+        } else {
+            unsigned bytesToWrite = 1 + sizeof(T);
+            if (bufferWritten + bytesToWrite > bufferSize) {
+                bufferSize += 256;
+                buffer = (unsigned char *)realloc(buffer, bufferSize);
+            }
+            buffer[bufferWritten++] = (run - 1) | 0x80;
+            *(T *)(buffer + bufferWritten) = data[0];
+            bufferWritten += sizeof(T);
+            data += run;
+            count -= run;
+        }
+    }
+    if (encodedSize)
+        *encodedSize = bufferWritten;
+    return buffer;
+}
+
+void * RLEEncode(const void * pixels, const unsigned bytesPerPixel, const unsigned count, unsigned * encodedSize)
+{
+    switch (bytesPerPixel) {
+    case 4:
+        return RLEEncode<int>(pixels, count, encodedSize);
+    case 2:
+        return RLEEncode<short>(pixels, count, encodedSize);
+    case 1:
+        return RLEEncode<char>(pixels, count, encodedSize);
+    default:
+        assert(0);
+        return NULL;
+    }
+}
+#endif
+}; // namespace android
+
+void Debug_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint internalformat;
+        GLsizei width;
+        GLsizei height;
+        GLint border;
+        GLenum format;
+        GLenum type;
+        const GLvoid* pixels;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.internalformat = internalformat;
+    caller.width = width;
+    caller.height = height;
+    caller.border = border;
+    caller.format = format;
+    caller.type = type;
+    caller.pixels = pixels;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(internalformat);
+    msg.set_arg3(width);
+    msg.set_arg4(height);
+    msg.set_arg5(border);
+    msg.set_arg6(format);
+    msg.set_arg7(type);
+    msg.set_arg8(reinterpret_cast<int>(pixels));
+
+    if (pixels) {
+        assert(internalformat == format);
+        assert(0 == border);
+
+        unsigned bytesPerPixel = GetBytesPerPixel(format, type);
+        assert(0 < bytesPerPixel);
+
+//        LOGD("GLESv2_dbg: glTexImage2D width=%d height=%d level=%d bytesPerPixel=%d",
+//             width, height, level, bytesPerPixel);
+#if USE_RLE
+        unsigned encodedSize = 0;
+        void * data = RLEEncode(pixels, bytesPerPixel, width * height, &encodedSize);
+        msg.set_data(data, encodedSize);
+        free(data);
+        if (encodedSize > bytesPerPixel * width * height)
+            LOGD("GLESv2_dbg: glTexImage2D sending data encodedSize=%d size=%d", encodedSize, bytesPerPixel * width * height);
+#else
+        msg.set_data(pixels, bytesPerPixel * width * height);
+#endif
+    }
+    
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexImage2D);
+}
+
+void Debug_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+    glesv2debugger::Message msg;
+    const bool expectResponse = false;
+    struct : public FunctionCall {
+        GLenum target;
+        GLint level;
+        GLint xoffset;
+        GLint yoffset;
+        GLsizei width;
+        GLsizei height;
+        GLenum format;
+        GLenum type;
+        const GLvoid* pixels;
+
+        const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) {
+            nsecs_t c0 = systemTime(timeMode);
+            _c->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            return 0;
+        }
+    } caller;
+    caller.target = target;
+    caller.level = level;
+    caller.xoffset = xoffset;
+    caller.yoffset = yoffset;
+    caller.width = width;
+    caller.height = height;
+    caller.format = format;
+    caller.type = type;
+    caller.pixels = pixels;
+
+    msg.set_arg0(target);
+    msg.set_arg1(level);
+    msg.set_arg2(xoffset);
+    msg.set_arg3(yoffset);
+    msg.set_arg4(width);
+    msg.set_arg5(height);
+    msg.set_arg6(format);
+    msg.set_arg7(type);
+    msg.set_arg8(reinterpret_cast<int>(pixels));
+
+    assert(pixels);
+    if (pixels) {
+        unsigned bytesPerPixel = GetBytesPerPixel(format, type);
+        assert(0 < bytesPerPixel);
+
+//        LOGD("GLESv2_dbg: glTexSubImage2D width=%d height=%d level=%d bytesPerPixel=%d",
+//             width, height, level, bytesPerPixel);
+
+#if USE_RLE
+        unsigned encodedSize = 0;
+        void * data = RLEEncode(pixels, bytesPerPixel, width * height, &encodedSize);
+        msg.set_data(data, encodedSize);
+        free(data);
+        if (encodedSize > bytesPerPixel * width * height)
+            LOGD("GLESv2_dbg: glTexImage2D sending data encodedSize=%d size=%d", encodedSize, bytesPerPixel * width * height);
+#else
+        msg.set_data(pixels, bytesPerPixel * width * height);
+#endif
+    }
+    
+    int * ret = MessageLoop(caller, msg, expectResponse,
+                            glesv2debugger::Message_Function_glTexSubImage2D);
+}
\ No newline at end of file
diff --git a/opengl/libs/GLES2_dbg/src/vertex.cpp b/opengl/libs/GLES2_dbg/src/vertex.cpp
new file mode 100644
index 0000000..52ce907
--- /dev/null
+++ b/opengl/libs/GLES2_dbg/src/vertex.cpp
@@ -0,0 +1,231 @@
+/*
+ ** 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 "header.h"
+
+namespace android
+{
+bool capture; // capture after each glDraw*
+
+void * RLEEncode(const void * pixels, const unsigned bytesPerPixel, const unsigned count, unsigned * encodedSize);
+}
+
+void Debug_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    const bool expectResponse = false;
+    msg.set_expect_response(expectResponse);
+    msg.set_function(glesv2debugger::Message_Function_glReadPixels);
+    msg.set_arg0(x);
+    msg.set_arg1(y);
+    msg.set_arg2(width);
+    msg.set_arg3(height);
+    msg.set_arg4(format);
+    msg.set_arg5(type);
+    msg.set_arg6(reinterpret_cast<int>(pixels));
+    //void * data = NULL;
+    //unsigned encodedSize = 0;
+    Send(msg, cmd);
+    float t = 0;
+    if (!expectResponse)
+        cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            dbg->hooks->gl.glReadPixels(x, y, width, height, format, type, pixels);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(glesv2debugger::Message_Function_glReadPixels);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            //data = RLEEncode(pixels, GetBytesPerPixel(format, type), width * height, &encodedSize);
+            msg.set_data(pixels, width * height * GetBytesPerPixel(format, type));
+            //msg.set_data(data, encodedSize);
+            //free(data);
+            c0 = systemTime(timeMode);
+            t = Send(msg, cmd);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_clock(t);
+            // time is total send time in seconds, clock is msg serialization time in seconds
+            msg.clear_data();
+            msg.set_expect_response(false);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            //Send(msg, cmd);
+            if (!expectResponse)
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return;
+        default:
+            assert(0); //GenerateCall(msg, cmd);
+            break;
+        }
+    }
+}
+
+void Debug_glDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    const bool expectResponse = false;
+    msg.set_expect_response(expectResponse);
+    msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
+    msg.set_arg0(mode);
+    msg.set_arg1(first);
+    msg.set_arg2(count);
+
+    msg.set_arg7(dbg->maxAttrib); // indicate capturing vertex data
+    if (dbg->hasNonVBOAttribs) {
+        std::string * const data = msg.mutable_data();
+        for (unsigned i = 0; i < count; i++)
+            dbg->Fetch(i + first, data);
+    }
+
+    void * pixels = NULL;
+    GLint readFormat = 0, readType = 0;
+    int viewport[4] = {};
+    Send(msg, cmd);
+    if (!expectResponse)
+        cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            dbg->hooks->gl.glDrawArrays(mode, first, count);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            Send(msg, cmd);
+            if (capture)
+                cmd.set_function(glesv2debugger::Message_Function_CAPTURE);
+            else if (!expectResponse)
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return;
+        case glesv2debugger::Message_Function_CAPTURE:
+            dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
+            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
+            LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
+                 viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
+            pixels = malloc(viewport[2] * viewport[3] * 4);
+            Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
+                               readFormat, readType, pixels);
+            free(pixels);
+            cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            break;
+        default:
+            assert(0); //GenerateCall(msg, cmd);
+            break;
+        }
+    }
+}
+
+template<typename T>
+static inline void FetchIndexed(const unsigned count, const T * indices,
+                                std::string * const data, const DbgContext * const ctx)
+{
+    for (unsigned i = 0; i < count; i++) {
+        if (!ctx->indexBuffer)
+            data->append((const char *)(indices + i), sizeof(*indices));
+        if (ctx->hasNonVBOAttribs)
+            ctx->Fetch(indices[i], data);
+    }
+}
+
+void Debug_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+    DbgContext * const dbg = getDbgContextThreadSpecific();
+    glesv2debugger::Message msg, cmd;
+    msg.set_context_id(reinterpret_cast<int>(dbg));
+    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
+    const bool expectResponse = false;
+    msg.set_expect_response(expectResponse);
+    msg.set_function(glesv2debugger::Message_Function_glDrawElements);
+    msg.set_arg0(mode);
+    msg.set_arg1(count);
+    msg.set_arg2(type);
+    msg.set_arg3(reinterpret_cast<int>(indices));
+
+    msg.set_arg7(dbg->maxAttrib); // indicate capturing vertex data
+    std::string * const data = msg.mutable_data();
+    if (GL_UNSIGNED_BYTE == type) {
+        if (dbg->indexBuffer)
+            FetchIndexed(count, (unsigned char *)dbg->indexBuffer->data + (unsigned long)indices, data, dbg);
+        else
+            FetchIndexed(count, (unsigned char *)indices, data, dbg);
+    } else if (GL_UNSIGNED_SHORT == type) {
+        if (dbg->indexBuffer)
+            FetchIndexed(count, (unsigned short *)((char *)dbg->indexBuffer->data + (unsigned long)indices), data, dbg);
+        else
+            FetchIndexed(count, (unsigned short *)indices, data, dbg);
+    } else
+        assert(0);
+
+    void * pixels = NULL;
+    GLint readFormat = 0, readType = 0;
+    int viewport[4] = {};
+    Send(msg, cmd);
+    if (!expectResponse)
+        cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    while (true) {
+        msg.Clear();
+        nsecs_t c0 = systemTime(timeMode);
+        switch (cmd.function()) {
+        case glesv2debugger::Message_Function_CONTINUE:
+            dbg->hooks->gl.glDrawElements(mode, count, type, indices);
+            msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
+            msg.set_context_id(reinterpret_cast<int>(dbg));
+            msg.set_function(glesv2debugger::Message_Function_glDrawElements);
+            msg.set_type(glesv2debugger::Message_Type_AfterCall);
+            msg.set_expect_response(expectResponse);
+            Send(msg, cmd);
+            if (capture)
+                cmd.set_function(glesv2debugger::Message_Function_CAPTURE);
+            else if (!expectResponse)
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            break;
+        case glesv2debugger::Message_Function_SKIP:
+            return;
+        case glesv2debugger::Message_Function_CAPTURE:
+            dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
+            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
+            LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
+                 viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
+            pixels = malloc(viewport[2] * viewport[3] * 4);
+            Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
+                               readFormat, readType, pixels);
+            free(pixels);
+            cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            break;
+        default:
+            assert(0); //GenerateCall(msg, cmd);
+            break;
+        }
+    }
+}
diff --git a/opengl/libs/debug.in b/opengl/libs/debug.in
new file mode 100644
index 0000000..882b2da
--- /dev/null
+++ b/opengl/libs/debug.in
@@ -0,0 +1,235 @@
+// the following functions are not defined in GLESv2_dbg
+TRACE_GL_VOID(glAlphaFunc, (GLenum func, GLclampf ref), (func, ref), 2, "GLenum", func, "GLclampf", ref)
+TRACE_GL_VOID(glAlphaFuncx, (GLenum func, GLclampx ref), (func, ref), 2, "GLenum", func, "GLclampx", ref)
+TRACE_GL_VOID(glAlphaFuncxOES, (GLenum func, GLclampx ref), (func, ref), 2, "GLenum", func, "GLclampx", ref)
+TRACE_GL_VOID(glBeginPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
+TRACE_GL_VOID(glBindFramebufferOES, (GLenum target, GLuint framebuffer), (target, framebuffer), 2, "GLenum", target, "GLuint", framebuffer)
+TRACE_GL_VOID(glBindRenderbufferOES, (GLenum target, GLuint renderbuffer), (target, renderbuffer), 2, "GLenum", target, "GLuint", renderbuffer)
+TRACE_GL_VOID(glBindVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
+TRACE_GL_VOID(glBlendEquationOES, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glBlendEquationSeparateOES, (GLenum modeRGB, GLenum modeAlpha), (modeRGB, modeAlpha), 2, "GLenum", modeRGB, "GLenum", modeAlpha)
+TRACE_GL_VOID(glBlendFuncSeparateOES, (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha), (srcRGB, dstRGB, srcAlpha, dstAlpha), 4, "GLenum", srcRGB, "GLenum", dstRGB, "GLenum", srcAlpha, "GLenum", dstAlpha)
+TRACE_GL(GLenum, glCheckFramebufferStatusOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glClearColorx, (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha), (red, green, blue, alpha), 4, "GLclampx", red, "GLclampx", green, "GLclampx", blue, "GLclampx", alpha)
+TRACE_GL_VOID(glClearColorxOES, (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha), (red, green, blue, alpha), 4, "GLclampx", red, "GLclampx", green, "GLclampx", blue, "GLclampx", alpha)
+TRACE_GL_VOID(glClearDepthfOES, (GLclampf depth), (depth), 1, "GLclampf", depth)
+TRACE_GL_VOID(glClearDepthx, (GLclampx depth), (depth), 1, "GLclampx", depth)
+TRACE_GL_VOID(glClearDepthxOES, (GLclampx depth), (depth), 1, "GLclampx", depth)
+TRACE_GL_VOID(glClientActiveTexture, (GLenum texture), (texture), 1, "GLenum", texture)
+TRACE_GL_VOID(glClipPlanef, (GLenum plane, const GLfloat *equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
+TRACE_GL_VOID(glClipPlanefIMG, (GLenum p, const GLfloat *eqn), (p, eqn), 2, "GLenum", p, "const GLfloat *", eqn)
+TRACE_GL_VOID(glClipPlanefOES, (GLenum plane, const GLfloat *equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
+TRACE_GL_VOID(glClipPlanex, (GLenum plane, const GLfixed *equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
+TRACE_GL_VOID(glClipPlanexIMG, (GLenum p, const GLfixed *eqn), (p, eqn), 2, "GLenum", p, "const GLfixed *", eqn)
+TRACE_GL_VOID(glClipPlanexOES, (GLenum plane, const GLfixed *equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
+TRACE_GL_VOID(glColor4f, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), (red, green, blue, alpha), 4, "GLfloat", red, "GLfloat", green, "GLfloat", blue, "GLfloat", alpha)
+TRACE_GL_VOID(glColor4ub, (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha), (red, green, blue, alpha), 4, "GLubyte", red, "GLubyte", green, "GLubyte", blue, "GLubyte", alpha)
+TRACE_GL_VOID(glColor4x, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
+TRACE_GL_VOID(glColor4xOES, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
+TRACE_GL_VOID(glColorPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glCompressedTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data), (target, level, internalformat, width, height, depth, border, imageSize, data), 9, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLsizei", imageSize, "const GLvoid*", data)
+TRACE_GL_VOID(glCompressedTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLsizei", imageSize, "const GLvoid*", data)
+TRACE_GL_VOID(glCopyTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, zoffset, x, y, width, height), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glCoverageMaskNV, (GLboolean mask), (mask), 1, "GLboolean", mask)
+TRACE_GL_VOID(glCoverageOperationNV, (GLenum operation), (operation), 1, "GLenum", operation)
+TRACE_GL_VOID(glCurrentPaletteMatrixOES, (GLuint matrixpaletteindex), (matrixpaletteindex), 1, "GLuint", matrixpaletteindex)
+TRACE_GL_VOID(glDeleteFencesNV, (GLsizei n, const GLuint *fences), (n, fences), 2, "GLsizei", n, "const GLuint *", fences)
+TRACE_GL_VOID(glDeleteFramebuffersOES, (GLsizei n, const GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "const GLuint*", framebuffers)
+TRACE_GL_VOID(glDeletePerfMonitorsAMD, (GLsizei n, GLuint *monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
+TRACE_GL_VOID(glDeleteRenderbuffersOES, (GLsizei n, const GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "const GLuint*", renderbuffers)
+TRACE_GL_VOID(glDeleteVertexArraysOES, (GLsizei n, const GLuint *arrays), (n, arrays), 2, "GLsizei", n, "const GLuint *", arrays)
+TRACE_GL_VOID(glDepthRangefOES, (GLclampf zNear, GLclampf zFar), (zNear, zFar), 2, "GLclampf", zNear, "GLclampf", zFar)
+TRACE_GL_VOID(glDepthRangex, (GLclampx zNear, GLclampx zFar), (zNear, zFar), 2, "GLclampx", zNear, "GLclampx", zFar)
+TRACE_GL_VOID(glDepthRangexOES, (GLclampx zNear, GLclampx zFar), (zNear, zFar), 2, "GLclampx", zNear, "GLclampx", zFar)
+TRACE_GL_VOID(glDisableClientState, (GLenum array), (array), 1, "GLenum", array)
+TRACE_GL_VOID(glDisableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
+TRACE_GL_VOID(glDiscardFramebufferEXT, (GLenum target, GLsizei numAttachments, const GLenum *attachments), (target, numAttachments, attachments), 3, "GLenum", target, "GLsizei", numAttachments, "const GLenum *", attachments)
+TRACE_GL_VOID(glDrawTexfOES, (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height), (x, y, z, width, height), 5, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", width, "GLfloat", height)
+TRACE_GL_VOID(glDrawTexfvOES, (const GLfloat *coords), (coords), 1, "const GLfloat *", coords)
+TRACE_GL_VOID(glDrawTexiOES, (GLint x, GLint y, GLint z, GLint width, GLint height), (x, y, z, width, height), 5, "GLint", x, "GLint", y, "GLint", z, "GLint", width, "GLint", height)
+TRACE_GL_VOID(glDrawTexivOES, (const GLint *coords), (coords), 1, "const GLint *", coords)
+TRACE_GL_VOID(glDrawTexsOES, (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height), (x, y, z, width, height), 5, "GLshort", x, "GLshort", y, "GLshort", z, "GLshort", width, "GLshort", height)
+TRACE_GL_VOID(glDrawTexsvOES, (const GLshort *coords), (coords), 1, "const GLshort *", coords)
+TRACE_GL_VOID(glDrawTexxOES, (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height), (x, y, z, width, height), 5, "GLfixed", x, "GLfixed", y, "GLfixed", z, "GLfixed", width, "GLfixed", height)
+TRACE_GL_VOID(glDrawTexxvOES, (const GLfixed *coords), (coords), 1, "const GLfixed *", coords)
+TRACE_GL_VOID(glEGLImageTargetRenderbufferStorageOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
+TRACE_GL_VOID(glEGLImageTargetTexture2DOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
+TRACE_GL_VOID(glEnableClientState, (GLenum array), (array), 1, "GLenum", array)
+TRACE_GL_VOID(glEnableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
+TRACE_GL_VOID(glEndPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
+TRACE_GL_VOID(glEndTilingQCOM, (GLbitfield preserveMask), (preserveMask), 1, "GLbitfield", preserveMask)
+TRACE_GL_VOID(glExtGetBufferPointervQCOM, (GLenum target, GLvoid **params), (target, params), 2, "GLenum", target, "GLvoid **", params)
+TRACE_GL_VOID(glExtGetBuffersQCOM, (GLuint *buffers, GLint maxBuffers, GLint *numBuffers), (buffers, maxBuffers, numBuffers), 3, "GLuint *", buffers, "GLint", maxBuffers, "GLint *", numBuffers)
+TRACE_GL_VOID(glExtGetFramebuffersQCOM, (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers), (framebuffers, maxFramebuffers, numFramebuffers), 3, "GLuint *", framebuffers, "GLint", maxFramebuffers, "GLint *", numFramebuffers)
+TRACE_GL_VOID(glExtGetProgramBinarySourceQCOM, (GLuint program, GLenum shadertype, GLchar *source, GLint *length), (program, shadertype, source, length), 4, "GLuint", program, "GLenum", shadertype, "GLchar *", source, "GLint *", length)
+TRACE_GL_VOID(glExtGetProgramsQCOM, (GLuint *programs, GLint maxPrograms, GLint *numPrograms), (programs, maxPrograms, numPrograms), 3, "GLuint *", programs, "GLint", maxPrograms, "GLint *", numPrograms)
+TRACE_GL_VOID(glExtGetRenderbuffersQCOM, (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers), (renderbuffers, maxRenderbuffers, numRenderbuffers), 3, "GLuint *", renderbuffers, "GLint", maxRenderbuffers, "GLint *", numRenderbuffers)
+TRACE_GL_VOID(glExtGetShadersQCOM, (GLuint *shaders, GLint maxShaders, GLint *numShaders), (shaders, maxShaders, numShaders), 3, "GLuint *", shaders, "GLint", maxShaders, "GLint *", numShaders)
+TRACE_GL_VOID(glExtGetTexLevelParameterivQCOM, (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params), (texture, face, level, pname, params), 5, "GLuint", texture, "GLenum", face, "GLint", level, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glExtGetTexSubImageQCOM, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "GLvoid *", texels)
+TRACE_GL_VOID(glExtGetTexturesQCOM, (GLuint *textures, GLint maxTextures, GLint *numTextures), (textures, maxTextures, numTextures), 3, "GLuint *", textures, "GLint", maxTextures, "GLint *", numTextures)
+TRACE_GL(GLboolean, glExtIsProgramBinaryQCOM, (GLuint program), (program), 1, "GLuint", program)
+TRACE_GL_VOID(glExtTexObjectStateOverrideiQCOM, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glFinishFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL_VOID(glFogf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glFogfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glFogx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glFogxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glFogxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glFogxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glFramebufferRenderbufferOES, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer), 4, "GLenum", target, "GLenum", attachment, "GLenum", renderbuffertarget, "GLuint", renderbuffer)
+TRACE_GL_VOID(glFramebufferTexture2DMultisampleIMG, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples), (target, attachment, textarget, texture, level, samples), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLsizei", samples)
+TRACE_GL_VOID(glFramebufferTexture2DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level), 5, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level)
+TRACE_GL_VOID(glFramebufferTexture3DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset), (target, attachment, textarget, texture, level, zoffset), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLint", zoffset)
+TRACE_GL_VOID(glFrustumf, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glFrustumfOES, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glFrustumx, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glFrustumxOES, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glGenFencesNV, (GLsizei n, GLuint *fences), (n, fences), 2, "GLsizei", n, "GLuint *", fences)
+TRACE_GL_VOID(glGenFramebuffersOES, (GLsizei n, GLuint* framebuffers), (n, framebuffers), 2, "GLsizei", n, "GLuint*", framebuffers)
+TRACE_GL_VOID(glGenPerfMonitorsAMD, (GLsizei n, GLuint *monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
+TRACE_GL_VOID(glGenRenderbuffersOES, (GLsizei n, GLuint* renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "GLuint*", renderbuffers)
+TRACE_GL_VOID(glGenVertexArraysOES, (GLsizei n, GLuint *arrays), (n, arrays), 2, "GLsizei", n, "GLuint *", arrays)
+TRACE_GL_VOID(glGenerateMipmapOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glGetBufferPointervOES, (GLenum target, GLenum pname, GLvoid ** params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLvoid **", params)
+TRACE_GL_VOID(glGetClipPlanef, (GLenum pname, GLfloat eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfloat", eqn)
+TRACE_GL_VOID(glGetClipPlanefOES, (GLenum pname, GLfloat eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfloat", eqn)
+TRACE_GL_VOID(glGetClipPlanex, (GLenum pname, GLfixed eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfixed", eqn)
+TRACE_GL_VOID(glGetClipPlanexOES, (GLenum pname, GLfixed eqn[4]), (pname, eqn), 2, "GLenum", pname, "GLfixed", eqn)
+TRACE_GL_VOID(glGetDriverControlStringQCOM, (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString), (driverControl, bufSize, length, driverControlString), 4, "GLuint", driverControl, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", driverControlString)
+TRACE_GL_VOID(glGetDriverControlsQCOM, (GLint *num, GLsizei size, GLuint *driverControls), (num, size, driverControls), 3, "GLint *", num, "GLsizei", size, "GLuint *", driverControls)
+TRACE_GL_VOID(glGetFenceivNV, (GLuint fence, GLenum pname, GLint *params), (fence, pname, params), 3, "GLuint", fence, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetFixedv, (GLenum pname, GLfixed *params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetFixedvOES, (GLenum pname, GLfixed *params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetFramebufferAttachmentParameterivOES, (GLenum target, GLenum attachment, GLenum pname, GLint* params), (target, attachment, pname, params), 4, "GLenum", target, "GLenum", attachment, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetLightfv, (GLenum light, GLenum pname, GLfloat *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetLightxv, (GLenum light, GLenum pname, GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetLightxvOES, (GLenum light, GLenum pname, GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetMaterialfv, (GLenum face, GLenum pname, GLfloat *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetMaterialxv, (GLenum face, GLenum pname, GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetMaterialxvOES, (GLenum face, GLenum pname, GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetPerfMonitorCounterDataAMD, (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten), (monitor, pname, dataSize, data, bytesWritten), 5, "GLuint", monitor, "GLenum", pname, "GLsizei", dataSize, "GLuint *", data, "GLint *", bytesWritten)
+TRACE_GL_VOID(glGetPerfMonitorCounterInfoAMD, (GLuint group, GLuint counter, GLenum pname, GLvoid *data), (group, counter, pname, data), 4, "GLuint", group, "GLuint", counter, "GLenum", pname, "GLvoid *", data)
+TRACE_GL_VOID(glGetPerfMonitorCounterStringAMD, (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString), (group, counter, bufSize, length, counterString), 5, "GLuint", group, "GLuint", counter, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", counterString)
+TRACE_GL_VOID(glGetPerfMonitorCountersAMD, (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters), (group, numCounters, maxActiveCounters, counterSize, counters), 5, "GLuint", group, "GLint *", numCounters, "GLint *", maxActiveCounters, "GLsizei", counterSize, "GLuint *", counters)
+TRACE_GL_VOID(glGetPerfMonitorGroupStringAMD, (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString), (group, bufSize, length, groupString), 4, "GLuint", group, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", groupString)
+TRACE_GL_VOID(glGetPerfMonitorGroupsAMD, (GLint *numGroups, GLsizei groupsSize, GLuint *groups), (numGroups, groupsSize, groups), 3, "GLint *", numGroups, "GLsizei", groupsSize, "GLuint *", groups)
+TRACE_GL_VOID(glGetPointerv, (GLenum pname, GLvoid **params), (pname, params), 2, "GLenum", pname, "GLvoid **", params)
+TRACE_GL_VOID(glGetProgramBinaryOES, (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary), (program, bufSize, length, binaryFormat, binary), 5, "GLuint", program, "GLsizei", bufSize, "GLsizei *", length, "GLenum *", binaryFormat, "GLvoid *", binary)
+TRACE_GL_VOID(glGetRenderbufferParameterivOES, (GLenum target, GLenum pname, GLint* params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint*", params)
+TRACE_GL_VOID(glGetTexEnvfv, (GLenum env, GLenum pname, GLfloat *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexEnviv, (GLenum env, GLenum pname, GLint *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexEnvxv, (GLenum env, GLenum pname, GLfixed *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexEnvxvOES, (GLenum env, GLenum pname, GLfixed *params), (env, pname, params), 3, "GLenum", env, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexGenfvOES, (GLenum coord, GLenum pname, GLfloat *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfloat *", params)
+TRACE_GL_VOID(glGetTexGenivOES, (GLenum coord, GLenum pname, GLint *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLint *", params)
+TRACE_GL_VOID(glGetTexGenxvOES, (GLenum coord, GLenum pname, GLfixed *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexParameterxv, (GLenum target, GLenum pname, GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
+TRACE_GL_VOID(glGetTexParameterxvOES, (GLenum target, GLenum pname, GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
+TRACE_GL(GLboolean, glIsFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL(GLboolean, glIsFramebufferOES, (GLuint framebuffer), (framebuffer), 1, "GLuint", framebuffer)
+TRACE_GL(GLboolean, glIsRenderbufferOES, (GLuint renderbuffer), (renderbuffer), 1, "GLuint", renderbuffer)
+TRACE_GL(GLboolean, glIsVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
+TRACE_GL_VOID(glLightModelf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glLightModelfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glLightModelx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightModelxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightModelxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightModelxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightf, (GLenum light, GLenum pname, GLfloat param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glLightfv, (GLenum light, GLenum pname, const GLfloat *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glLightx, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightxOES, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glLightxv, (GLenum light, GLenum pname, const GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLightxvOES, (GLenum light, GLenum pname, const GLfixed *params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glLineWidthx, (GLfixed width), (width), 1, "GLfixed", width)
+TRACE_GL_VOID(glLineWidthxOES, (GLfixed width), (width), 1, "GLfixed", width)
+TRACE_GL_VOID(glLoadIdentity, (void), (), 0)
+TRACE_GL_VOID(glLoadMatrixf, (const GLfloat *m), (m), 1, "const GLfloat *", m)
+TRACE_GL_VOID(glLoadMatrixx, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glLoadMatrixxOES, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glLoadPaletteFromModelViewMatrixOES, (void), (), 0)
+TRACE_GL_VOID(glLogicOp, (GLenum opcode), (opcode), 1, "GLenum", opcode)
+TRACE_GL(void*, glMapBufferOES, (GLenum target, GLenum access), (target, access), 2, "GLenum", target, "GLenum", access)
+TRACE_GL_VOID(glMaterialf, (GLenum face, GLenum pname, GLfloat param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glMaterialfv, (GLenum face, GLenum pname, const GLfloat *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glMaterialx, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glMaterialxOES, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glMaterialxv, (GLenum face, GLenum pname, const GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glMaterialxvOES, (GLenum face, GLenum pname, const GLfixed *params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glMatrixIndexPointerOES, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glMatrixMode, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glMultMatrixf, (const GLfloat *m), (m), 1, "const GLfloat *", m)
+TRACE_GL_VOID(glMultMatrixx, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glMultMatrixxOES, (const GLfixed *m), (m), 1, "const GLfixed *", m)
+TRACE_GL_VOID(glMultiDrawArraysEXT, (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount), (mode, first, count, primcount), 4, "GLenum", mode, "GLint *", first, "GLsizei *", count, "GLsizei", primcount)
+TRACE_GL_VOID(glMultiDrawElementsEXT, (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "const GLsizei *", count, "GLenum", type, "const GLvoid* *", indices, "GLsizei", primcount)
+TRACE_GL_VOID(glMultiTexCoord4f, (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q), (target, s, t, r, q), 5, "GLenum", target, "GLfloat", s, "GLfloat", t, "GLfloat", r, "GLfloat", q)
+TRACE_GL_VOID(glMultiTexCoord4x, (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (target, s, t, r, q), 5, "GLenum", target, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
+TRACE_GL_VOID(glMultiTexCoord4xOES, (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (target, s, t, r, q), 5, "GLenum", target, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
+TRACE_GL_VOID(glNormal3f, (GLfloat nx, GLfloat ny, GLfloat nz), (nx, ny, nz), 3, "GLfloat", nx, "GLfloat", ny, "GLfloat", nz)
+TRACE_GL_VOID(glNormal3x, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
+TRACE_GL_VOID(glNormal3xOES, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
+TRACE_GL_VOID(glNormalPointer, (GLenum type, GLsizei stride, const GLvoid *pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glOrthof, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glOrthofOES, (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfloat", left, "GLfloat", right, "GLfloat", bottom, "GLfloat", top, "GLfloat", zNear, "GLfloat", zFar)
+TRACE_GL_VOID(glOrthox, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glOrthoxOES, (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar), (left, right, bottom, top, zNear, zFar), 6, "GLfixed", left, "GLfixed", right, "GLfixed", bottom, "GLfixed", top, "GLfixed", zNear, "GLfixed", zFar)
+TRACE_GL_VOID(glPointParameterf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glPointParameterfv, (GLenum pname, const GLfloat *params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glPointParameterx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glPointParameterxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glPointParameterxv, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glPointParameterxvOES, (GLenum pname, const GLfixed *params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glPointSize, (GLfloat size), (size), 1, "GLfloat", size)
+TRACE_GL_VOID(glPointSizePointerOES, (GLenum type, GLsizei stride, const GLvoid *pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glPointSizex, (GLfixed size), (size), 1, "GLfixed", size)
+TRACE_GL_VOID(glPointSizexOES, (GLfixed size), (size), 1, "GLfixed", size)
+TRACE_GL_VOID(glPolygonOffsetx, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
+TRACE_GL_VOID(glPolygonOffsetxOES, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
+TRACE_GL_VOID(glPopMatrix, (void), (), 0)
+TRACE_GL_VOID(glProgramBinaryOES, (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length), (program, binaryFormat, binary, length), 4, "GLuint", program, "GLenum", binaryFormat, "const GLvoid *", binary, "GLint", length)
+TRACE_GL_VOID(glPushMatrix, (void), (), 0)
+TRACE_GL(GLbitfield, glQueryMatrixxOES, (GLfixed mantissa[16], GLint exponent[16]), (mantissa, exponent), 2, "GLfixed", mantissa, "GLint", exponent)
+TRACE_GL_VOID(glRenderbufferStorageMultisampleIMG, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRenderbufferStorageOES, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height), (target, internalformat, width, height), 4, "GLenum", target, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
+TRACE_GL_VOID(glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z), (angle, x, y, z), 4, "GLfloat", angle, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glRotatex, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glRotatexOES, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glSampleCoveragex, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
+TRACE_GL_VOID(glSampleCoveragexOES, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
+TRACE_GL_VOID(glScalef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glScalex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glScalexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glSelectPerfMonitorCountersAMD, (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList), (monitor, enable, group, numCounters, countersList), 5, "GLuint", monitor, "GLboolean", enable, "GLuint", group, "GLint", numCounters, "GLuint *", countersList)
+TRACE_GL_VOID(glSetFenceNV, (GLuint fence, GLenum condition), (fence, condition), 2, "GLuint", fence, "GLenum", condition)
+TRACE_GL_VOID(glShadeModel, (GLenum mode), (mode), 1, "GLenum", mode)
+TRACE_GL_VOID(glStartTilingQCOM, (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask), (x, y, width, height, preserveMask), 5, "GLuint", x, "GLuint", y, "GLuint", width, "GLuint", height, "GLbitfield", preserveMask)
+TRACE_GL(GLboolean, glTestFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
+TRACE_GL_VOID(glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glTexEnvf, (GLenum target, GLenum pname, GLfloat param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexEnvfv, (GLenum target, GLenum pname, const GLfloat *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexEnvi, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexEnviv, (GLenum target, GLenum pname, const GLint *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexEnvx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexEnvxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexEnvxv, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexEnvxvOES, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexGenfOES, (GLenum coord, GLenum pname, GLfloat param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfloat", param)
+TRACE_GL_VOID(glTexGenfvOES, (GLenum coord, GLenum pname, const GLfloat *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfloat *", params)
+TRACE_GL_VOID(glTexGeniOES, (GLenum coord, GLenum pname, GLint param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLint", param)
+TRACE_GL_VOID(glTexGenivOES, (GLenum coord, GLenum pname, const GLint *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLint *", params)
+TRACE_GL_VOID(glTexGenxOES, (GLenum coord, GLenum pname, GLfixed param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexGenxvOES, (GLenum coord, GLenum pname, const GLfixed *params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels), (target, level, internalformat, width, height, depth, border, format, type, pixels), 10, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLenum", format, "GLenum", type, "const GLvoid*", pixels)
+TRACE_GL_VOID(glTexParameterx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexParameterxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
+TRACE_GL_VOID(glTexParameterxv, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexParameterxvOES, (GLenum target, GLenum pname, const GLfixed *params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
+TRACE_GL_VOID(glTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "const GLvoid*", pixels)
+TRACE_GL_VOID(glTranslatef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
+TRACE_GL_VOID(glTranslatex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL_VOID(glTranslatexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
+TRACE_GL(GLboolean, glUnmapBufferOES, (GLenum target), (target), 1, "GLenum", target)
+TRACE_GL_VOID(glVertexPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
+TRACE_GL_VOID(glWeightPointerOES, (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const GLvoid *", pointer)
diff --git a/opengl/libs/glesv2dbg.h b/opengl/libs/glesv2dbg.h
new file mode 100644
index 0000000..b988eb7
--- /dev/null
+++ b/opengl/libs/glesv2dbg.h
@@ -0,0 +1,32 @@
+/*
+ ** 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 _GLESV2_DBG_H_
+#define _GLESV2_DBG_H_
+
+namespace android
+{
+    struct DbgContext;
+    
+    DbgContext * CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks);
+    void DestroyDbgContext(DbgContext * const dbg);
+    
+    void StartDebugServer(); // create and bind socket if haven't already
+    void StopDebugServer(); // close socket if open
+    
+}; // namespace android
+
+#endif // #ifndef _GLESV2_DBG_H_
diff --git a/opengl/libs/glesv2dbg_functions.h b/opengl/libs/glesv2dbg_functions.h
new file mode 100644
index 0000000..2d70032
--- /dev/null
+++ b/opengl/libs/glesv2dbg_functions.h
@@ -0,0 +1,381 @@
+extern "C"
+{
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar* name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBindVertexArrayOES, GLuint array)
+GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glBlendEquation,  GLenum mode )
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glClearDepthx, GLclampx depth)
+GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat *eqn)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed *eqn)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCoverageMaskNV, GLboolean mask)
+GL_ENTRY(void, glCoverageOperationNV, GLenum operation)
+GL_ENTRY(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glEndTilingQCOM, GLbitfield preserveMask)
+GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, GLvoid **params)
+GL_ENTRY(void, glExtGetBuffersQCOM, GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
+GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
+GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar *source, GLint *length)
+GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms)
+GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
+GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders)
+GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels)
+GL_ENTRY(void, glExtGetTexturesQCOM, GLuint *textures, GLint maxTextures, GLint *numTextures)
+GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program)
+GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture2DMultisampleIMG, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const GLchar* name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, GLvoid ** params)
+GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, GLvoid *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPointerv, GLenum pname, GLvoid **params)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const GLchar* name)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, GLvoid** pointer)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLineWidthx, GLfixed width)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glLoadIdentity, void)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, GLint *first, GLsizei *count, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length)
+GL_ENTRY(void, glPushMatrix, void)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageMultisampleIMG, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+GL_ENTRY(void, glStartTilingQCOM, GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform1i, GLint location, GLint x)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glUseProgram, GLuint program)
+GL_ENTRY(void, glValidateProgram, GLuint program)
+GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+
+
+}
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..84ac927
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/values-ar-xlarge/strings.xml b/packages/SystemUI/res/values-ar-xlarge/strings.xml
index d4fb873..af0eed0 100644
--- a/packages/SystemUI/res/values-ar-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ar-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"جارٍ البحث عن GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"تم تعيين الموقع بواسطة GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"إيقاف التنبيهات"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"انقر هنا لإعادة تشغيل التنبيهات."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 530704b..486dacc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"الإعدادات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"وضع الطائرة"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"تأمين اتجاه الشاشة"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"كتم"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"تلقائي"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"التنبيهات"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"تم إنشاء الاتصال بالإنترنت عن طريق البلوتوث."</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"تهيئة طرق الإدخال"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"استخدام لوحة المفاتيح الفعلية"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg-xlarge/strings.xml b/packages/SystemUI/res/values-bg-xlarge/strings.xml
index 4e730ae..d44366d 100644
--- a/packages/SystemUI/res/values-bg-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-bg-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: има връзка"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Търси се GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Местоположението е зададено от GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Известията са изключени"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Докоснете тук, за да включите отново известията."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index cc4395f..df6ef71 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Настройки"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Самолетен режим"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Заключване на ориентацията"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"БЕЗ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТ."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Известия"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth има връзка с тетъринг"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Конфигуриране на въвеждането"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Използване на физ. клав."</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca-xlarge/strings.xml b/packages/SystemUI/res/values-ca-xlarge/strings.xml
index 9fc74d0..a0ace2c 100644
--- a/packages/SystemUI/res/values-ca-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ca-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connectat"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"S\'està cercant un GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"S\'ha establert la ubicació per GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notificacions desactivades"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Pica aquí per tornar a activar les notificacions."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index af78e07..2993e8b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuració"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode d\'avió"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquejar orientació pantalla"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Silen."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificacions"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth sense fil"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configura mètodes d\'entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilitza un teclat físic"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs-xlarge/strings.xml b/packages/SystemUI/res/values-cs-xlarge/strings.xml
index 05b1248..5fe365c 100644
--- a/packages/SystemUI/res/values-cs-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-cs-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: připojeno"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Vyhledávání satelitů GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Poloha nastavena pomocí GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Oznámení jsou vypnuta"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Chcete-li oznámení znovu zapnout, klepněte sem."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 37def5e..29ab1a7 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavení"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim V letadle"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Uzamknout orientaci obrazovky"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ZTLUM."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Oznámení"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Datové připojení Bluetooth se sdílí"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Nakonfigurovat metody vstupu"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Použít fyz. klávesnici"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da-xlarge/strings.xml b/packages/SystemUI/res/values-da-xlarge/strings.xml
index dd20e64..ae430b3 100644
--- a/packages/SystemUI/res/values-da-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-da-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi er forbundet"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Søger efter GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Placeringen er angivet ved hjælp af GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Meddelelser: Fra"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Tryk her for at slå meddelelser til igen."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index a0875d3..81122a8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Indstillinger"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flytilstand"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lås skærmretning"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"LYDLØS"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meddelelser"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-tethering anvendt"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurer inputmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Brug fysisk tastatur"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de-xlarge/strings.xml b/packages/SystemUI/res/values-de-xlarge/strings.xml
index cc782da..825cd0d 100644
--- a/packages/SystemUI/res/values-de-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-de-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Mit WLAN verbunden"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Suche nach GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Standort durch GPS festgelegt"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Benachrichtigungen aus"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Tippen Sie hier, um Benachrichtigungen wieder einzuschalten."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a9d2e79..1ea87e8 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -34,19 +34,14 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Einstellungen"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flugmodus"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bildschirmausrichtung sperren"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"STUMM"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Benachrichtigungen"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Zuletzt verwendet"</string>
-    <string name="recent_tasks_empty" msgid="1905484479067697884">"Keine zuletzt verwendeten Anwendungen"</string>
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Keine neuen Anwendungen"</string>
     <string name="recent_tasks_app_label" msgid="3796483981246752469">"Google Apps"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-Tethering aktiv"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Eingabemethoden konfigurieren"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Physische Tastatur"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el-xlarge/strings.xml b/packages/SystemUI/res/values-el-xlarge/strings.xml
index 4f7814a..4902bb5 100644
--- a/packages/SystemUI/res/values-el-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-el-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: συνδέθηκε"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Αναζήτηση για GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Ρύθμιση τοποθεσίας με GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Ειδοποιήσεις ανενεργές"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Πατήστε εδώ για να ενεργοποιήσετε τις ειδοποιήσεις"</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 2370c26..cd412f4 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ρυθμίσεις"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Λειτουργία πτήσης"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Κλείδωμα προσανατολ. οθόνης"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ΣΙΓΑΣΗ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ΑΥΤΟΜ."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ειδοποιήσεις"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Έγινε σύνδεση μέσω Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Διαμόρφωση μεθόδων εισαγωγής"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Χρήση κανονικού πληκτρολ."</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml
index 68986f0..de1eb52 100644
--- a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi connected"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Searching for GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Location set by GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notifications off"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Tap here to turn notifications back on."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 2a7a7eb..2bd662b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Settings"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Airplane mode"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lock screen orientation"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tethered"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configure input methods"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Use physical keyboard"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml
index fa9b762..2ace144 100644
--- a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"WiFi conectado"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"La ubicación se estableció por GPS."</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notificaciones desactivadas"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Presiona aquí para volver a activar las notificaciones."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 60beb13..2c50160 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="7164937344850004466">"IU del sistema"</string>
+    <string name="app_label" msgid="7164937344850004466">"Sistema UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
     <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molestar"</string>
     <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificaciones"</string>
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuración"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloq orient de pant"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SILENC"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificaciones"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Usar teclado físico"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-xlarge/strings.xml b/packages/SystemUI/res/values-es-xlarge/strings.xml
index a7588da..dd490fb 100644
--- a/packages/SystemUI/res/values-es-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-es-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Con conexión WiFi"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Ubicación definida por GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notificaciones desactivadas"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Toca aquí para volver a activar las notificaciones."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 8d39377..8d9cc5c 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ajustes"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquear orientación pantalla"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SILENC"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificaciones"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de introducción"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizar teclado físico"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa-xlarge/strings.xml b/packages/SystemUI/res/values-fa-xlarge/strings.xml
index a8e2543..6e0654d 100644
--- a/packages/SystemUI/res/values-fa-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-fa-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل شد"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"جستجوی GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"مکان تنظیم شده توسط GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"اعلان ها خاموش"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"برای روشن کردن مجدد اعلان ها، اینجا را ضربه بزنید."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 1474340..1e0f1e9 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"تنظیمات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"حالت هواپیما"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"قفل جهت صفحه"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بیصدا"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان ها"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"پیکربندی روش های ورودی"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"از صفحه کلید فیزیکی استفاده کنید"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi-xlarge/strings.xml b/packages/SystemUI/res/values-fi-xlarge/strings.xml
index 754c577..7d49e9b 100644
--- a/packages/SystemUI/res/values-fi-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-fi-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wifi yhdistetty"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Haetaan GPS-yhteyttä"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Sijainti määritetty GPS:n avulla"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Ilmoitukset pois käytöstä"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 12d74e6..e2f935a 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Asetukset"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WiFi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lentokonetila"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lukitse ruudun suunta"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ÄÄNET."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ilmoitukset"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth yhdistetty"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Määritä syöttötavat"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Käytä fyysistä näppäimistöä"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr-xlarge/strings.xml b/packages/SystemUI/res/values-fr-xlarge/strings.xml
index 08f673d..98dc6c0 100644
--- a/packages/SystemUI/res/values-fr-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-fr-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Connecté au Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Recherche de GPS en cours"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Position définie par GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notifications désactivées"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Appuyez ici pour réactiver les notifications."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b507c98..9bd1886 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Paramètres"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode Avion"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Verrouiller orientation écran"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUET"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Connexion Bluetooth partagée"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurer les modes de saisie"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utiliser clavier physique"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr-xlarge/strings.xml b/packages/SystemUI/res/values-hr-xlarge/strings.xml
index b6e15dc..08adaf0 100644
--- a/packages/SystemUI/res/values-hr-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-hr-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: povezano"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Pretraživanje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokaciju utvrdio GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Obavijesti isključene"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f568310..8034eb7 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Postavke"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Način rada u zrakoplovu"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Zaključaj orijentaciju zaslona"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Bez zv."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obavijesti"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth posredno povezan"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfiguriraj načine ulaza"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Rabi fizičku tipkovnicu"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu-xlarge/strings.xml b/packages/SystemUI/res/values-hu-xlarge/strings.xml
index fe2e5ee..41d60fc 100644
--- a/packages/SystemUI/res/values-hu-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-hu-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi csatlakozva"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS keresése"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"A GPS beállította a helyet"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Értesítések kikapcsolva"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Itt érintse meg az értesítések bekapcsolásához."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 1299991..9a91b13 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Beállítások"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Repülőgép üzemmód"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Telefon tájolásának zárolása"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NÉMÍT"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Értesítések"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth megosztva"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Beviteli módok konfigurálása"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Valódi bill. használata"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in-xlarge/strings.xml b/packages/SystemUI/res/values-in-xlarge/strings.xml
index a4ca341..8d95060 100644
--- a/packages/SystemUI/res/values-in-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-in-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi tersambung"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Menelusuri GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokasi yang disetel oleh GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Pemberitahuan mati"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Ketuk di sini untuk menghidupkan lagi pemberitahuan."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 259a358..8d3cfb1 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setelan"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode pesawat"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Kunci orientasi layar"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"BISUKAN"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pemberitahuan"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tertambat"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurasikan metode masukan"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gunakan keyboard fisik"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it-xlarge/strings.xml b/packages/SystemUI/res/values-it-xlarge/strings.xml
index 24d88744..68393fb 100644
--- a/packages/SystemUI/res/values-it-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-it-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connesso"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Ricerca del GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Posizione stabilita dal GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notifiche disattivate"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Tocca qui per riattivare le notifiche."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 99f321d..9e7f53a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Impostazioni"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modalità aereo"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Blocca orientamento schermo"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifiche"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth con tethering"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configura metodi di input"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizza tastiera fisica"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw-xlarge/strings.xml b/packages/SystemUI/res/values-iw-xlarge/strings.xml
index 97172b8..fd3ce0e 100644
--- a/packages/SystemUI/res/values-iw-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-iw-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi מחובר"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"מחפש GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"מיקום מוגדר על ידי GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"מצב התראות כבוי"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"הקש כאן כדי להפעיל מחדש את ההתראות."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ff7114a..a242d04 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"הגדרות"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"מצב טיסה"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"נעל כיוון מסך"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"השתק"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"אוטומטי"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"התראות"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth קשור"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"הגדר שיטות קלט"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"השתמש במקלדת הפיזית"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja-xlarge/strings.xml b/packages/SystemUI/res/values-ja-xlarge/strings.xml
index e67e0e1..c7c0824 100644
--- a/packages/SystemUI/res/values-ja-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ja-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi接続済み"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"GPSで検索中"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"GPSにより現在地が設定されました"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"通知OFF"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"通知を有効にするにはここをタップします。"</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 90708a1..869688c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"機内モード"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"画面の向きをロック"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ミュート"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"オート"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetoothテザリング接続"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"入力方法の設定"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"物理キーボードを使用"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko-xlarge/strings.xml b/packages/SystemUI/res/values-ko-xlarge/strings.xml
index e28ac63..3777154 100644
--- a/packages/SystemUI/res/values-ko-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ko-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 연결됨"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS 검색"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS에서 설정한 위치"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"알림 사용 안함"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"알림을 다시 사용하려면 여기를 누르세요."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 97847f1..32ae7e7 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"설정"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"비행기 모드"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"화면 방향 잠금"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"무시"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"자동"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"알림"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"블루투스 테더링됨"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"입력 방법 구성"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"물리적 키보드 사용"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt-xlarge/strings.xml b/packages/SystemUI/res/values-lt-xlarge/strings.xml
index 12e8bb3..90dd501 100644
--- a/packages/SystemUI/res/values-lt-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-lt-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Prisijungta prie „Wi-Fi“"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Ieškoma GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS nustatyta vieta"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Pranešimai išjungti"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Palieskite čia, kad vėl įjungtumėte pranešimus."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 60cd207..01cdffd 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nustatymai"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lėktuvo režimas"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Užfiksuoti ekrano orientaciją"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NUTILD."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pranešimai"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"„Bluetooth“ susieta"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigūruoti įvesties metodus"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Naudoti fizinę klaviatūrą"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv-xlarge/strings.xml b/packages/SystemUI/res/values-lv-xlarge/strings.xml
index aecb471..c533ecb 100644
--- a/packages/SystemUI/res/values-lv-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-lv-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Izv. sav. ar Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Notiek GPS meklēšana..."</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS iestatītā atrašanās vieta"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Paziņojumi ir izslēgti."</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Pieskarieties šeit, lai vēlreiz ieslēgtu paziņojumus."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 634ce19..817e1d5 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Iestatījumi"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lidmašīnas režīms"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloķēt ekrāna orientāciju"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"IZ. SK."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Paziņojumi"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth piesaiste"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurēt ievades metodes"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Izmantot fizisku tastatūru"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb-xlarge/strings.xml b/packages/SystemUI/res/values-nb-xlarge/strings.xml
index 717ee79..2bf63e8 100644
--- a/packages/SystemUI/res/values-nb-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-nb-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: tilkoblet"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Søker etter GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Posisjon angitt av GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Varslinger er slått av"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Trykk her for å slå på varslinger igjen."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index e9c267e..bb96483 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Innstillinger"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Trådløse nettverk"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flymodus"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lås skjermretning"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPET"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Varslinger"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tilknyttet"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurer inndatametoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Bruk fysisk tastatur"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl-xlarge/strings.xml b/packages/SystemUI/res/values-nl-xlarge/strings.xml
index 7c84a7a..7a63401 100644
--- a/packages/SystemUI/res/values-nl-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-nl-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Verbonden via Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Zoeken naar GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Locatie bepaald met GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Meldingen uit"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Tik hier om meldingen weer in te schakelen."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e879592..faf3f32 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Instellingen"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Vliegmodus"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Schermstand vergrendelen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPEN"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meldingen"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth getetherd"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Invoermethoden configureren"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Fysiek toetsenbord gebruiken"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl-xlarge/strings.xml b/packages/SystemUI/res/values-pl-xlarge/strings.xml
index 9db1cab..1334b70 100644
--- a/packages/SystemUI/res/values-pl-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-pl-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: połączono"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Wyszukiwanie sygnału GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokalizacja ustawiona wg GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Powiadomienia wyłączone"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Dotknij tutaj, aby z powrotem włączyć powiadomienia."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d6c138b..77ae7e7 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ustawienia"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Tryb samolotowy"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Zablokuj orientację ekranu"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"WYGAŚ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Powiadomienia"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth – podłączono"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfiguruj metody wprowadzania"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Używaj klawiatury fizycznej"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml b/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml
index 7860208..a5d6bac 100644
--- a/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi ligado"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"A procurar GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Localização definida por GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notificações desativadas"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Toque aqui para voltar a ativar as notificações."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 506b072..1215415 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Definições"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo de avião"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquear orientação do ecrã"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"D. SOM"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificações"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ligado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizar teclado físico"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-xlarge/strings.xml b/packages/SystemUI/res/values-pt-xlarge/strings.xml
index 2a1786d..5209ab9 100644
--- a/packages/SystemUI/res/values-pt-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-pt-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectado"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Procurando GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Localização definida por GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notificações desativadas"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Toque aqui para ativar novamente as notificações."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5db5277..1f4afb7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configurações"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo para avião"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquear orientação de tela"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUDO"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificações"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth vinculado"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Usar o teclado físico"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index fd350cb..d4d4600 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -42,7 +42,7 @@
     <skip />
     <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
     <skip />
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
+    <!-- no translation found for status_bar_settings_rotation_lock (8361452930058000609) -->
     <skip />
     <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
     <skip />
@@ -61,8 +61,4 @@
     <skip />
     <!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) -->
     <skip />
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro-xlarge/strings.xml b/packages/SystemUI/res/values-ro-xlarge/strings.xml
index 21fd0ad..2dedd3b 100644
--- a/packages/SystemUI/res/values-ro-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ro-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectat"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Se caută dispozitivul GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Locaţie setată prin GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Notificările sunt dezactivate"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Apăsaţi aici pentru a reactiva notificările."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 98d68b5..c3bcc97 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setări"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mod Avion"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Blocaţi orientarea ecranului"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEZAC."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificări"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Conectat prin tethering prin Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configuraţi metode de intrare"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizaţi tastat. fizică"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru-xlarge/strings.xml b/packages/SystemUI/res/values-ru-xlarge/strings.xml
index bc31fb1..212fa83 100644
--- a/packages/SystemUI/res/values-ru-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ru-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi подкл."</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Выполняется поиск при помощи GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Местоположение установлено при помощи GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Показ уведомлений отключен"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Нажмите здесь, чтобы снова включить показ уведомлений."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9306274..e53fbd2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Настройки"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим полета"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Закрепить ориентацию экрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ВЫКЛ."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТО"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Уведомления"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Общий модем доступен через Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Настроить способ ввода"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Использовать физическую клавиатуру"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk-xlarge/strings.xml b/packages/SystemUI/res/values-sk-xlarge/strings.xml
index ee9e613..0fcdd4a 100644
--- a/packages/SystemUI/res/values-sk-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sk-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: pripojené"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Hľadanie signálu GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Poloha určená pomocou GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Upozornenia sú vypnuté"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Klepnutím tu upozornenia znova povolíte."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index a3475ac..bf316cc 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavenia"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim V lietadle"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Uzamknúť orientáciu obrazovky"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"STLMIŤ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Upozornenia"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Zdieľané dátové pripojenie cez Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurovať metódy vstupu"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Použiť fyzickú klávesnicu"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl-xlarge/strings.xml b/packages/SystemUI/res/values-sl-xlarge/strings.xml
index 57ed9a7..615c565 100644
--- a/packages/SystemUI/res/values-sl-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sl-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi – povezano"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Iskanje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokacija nastavljena z GPS-om"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Obvestila izklopljena"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Tapnite tukaj, da spet vklopite obvestila."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 80a5674..c0a7f04 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavitve"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Način za letalo"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Zakleni usmerjenost zaslona"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TIHO"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"SAMOD."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obvestila"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetna povezava prek Bluetootha"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Nastavitev načinov vnosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Uporabi fizično tipkovn."</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr-xlarge/strings.xml b/packages/SystemUI/res/values-sr-xlarge/strings.xml
index 95fbc2f..d66765b 100644
--- a/packages/SystemUI/res/values-sr-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sr-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi је повезан"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Тражи се GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Локацију је подесио GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Обавештења су искључена"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Додирните овде да бисте поново укључили обавештења."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 427b0d9..bd00a9c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Подешавања"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим рада у авиону"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Закључавање положаја екрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"УГАСИ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АУТОM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Обавештења"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Веза преко Bluetooth-а"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Конфигуриши методе уноса"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Користи физичку тастатуру"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv-xlarge/strings.xml b/packages/SystemUI/res/values-sv-xlarge/strings.xml
index ce608c2..b53269e 100644
--- a/packages/SystemUI/res/values-sv-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sv-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi-ansluten"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Sökning efter GPS pågår"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Platsen har identifierats av GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Aviseringar inaktiverade"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Knacka lätt här om du vill aktivera aviseringar igen."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 5612457..3d8f3c9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Inställningar"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flygplansläge"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lås bildskärmens riktning"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TYST"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Aviseringar"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetdelning via Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurera inmatningsmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Använd fysiska tangenter"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th-xlarge/strings.xml b/packages/SystemUI/res/values-th-xlarge/strings.xml
index 824de38..8222140 100644
--- a/packages/SystemUI/res/values-th-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-th-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"เชื่อมต่อ Wi-Fi แล้ว"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"การค้นหาสำหรับ GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"ตำแหน่งที่กำหนดโดย GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"การแจ้งเตือนปิดอยู่"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8ee8ee5..c42e26d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"การตั้งค่า"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"โหมดใช้งานบนเครื่องบิน"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"ล็อกแนวหน้าจอ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ปิดเสียง"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"อัตโนมัติ"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"การแจ้งเตือน"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"บลูทูธที่ปล่อยสัญญาณ"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"กำหนดค่าวิธีการป้อนข้อมูล"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"ใช้แป้นพิมพ์จริง"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl-xlarge/strings.xml b/packages/SystemUI/res/values-tl-xlarge/strings.xml
index 582adbc..0eef090 100644
--- a/packages/SystemUI/res/values-tl-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-tl-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Konektado ang WiFi"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Naghahanap ng GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Lokasyon na itinatakda ng GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Naka-off ang mga notification"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Mag-tap dito upang i-on muli ang mga notification."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 22ddda7..1244945 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Mga Setting"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Airplane mode"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Naka-lock na screen orientation"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Mga Notification"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Na-tether ang bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"I-configure paraan ng input"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gamitin ang pisikal na keyboard"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr-xlarge/strings.xml b/packages/SystemUI/res/values-tr-xlarge/strings.xml
index 6db515f..8c382fb 100644
--- a/packages/SystemUI/res/values-tr-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-tr-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Kablosuz bağlandı"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"GPS aranıyor"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Konum GPS ile belirlendi"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Bildirimler kapalı"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a7c9d4c..e911b42 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ayarlar"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Kablosuz"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Uçak modu"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Ekran yönünü kilitle"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"KAPAT"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OTOMTK"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Bildirimler"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth paylaşımı tamam"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Giriş yöntemlerini yapılandır"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Fiziksel klavyeyi kullan"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk-xlarge/strings.xml b/packages/SystemUI/res/values-uk-xlarge/strings.xml
index 81e50c0..6b1b193 100644
--- a/packages/SystemUI/res/values-uk-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-uk-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi під\'єднано"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Виконується пошук за допомогою GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Місцезнаходження встановлено за допомогою GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Сповіщення вимкнено"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Торкніться тут, щоб знову ввімкнути сповіщення."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 56f4c06..963a50f 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Налаштування"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим польоту"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Заблокувати орієнтацію екрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ІГНОР."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТОМ."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Сповіщення"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Створено прив\'язку Bluetooth"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Налаштувати методи введення"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Викор. реальну клавіатуру"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi-xlarge/strings.xml b/packages/SystemUI/res/values-vi-xlarge/strings.xml
index 6382fae..b44e1c3 100644
--- a/packages/SystemUI/res/values-vi-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-vi-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Đã kết nối Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"Tìm kiếm GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"Vị trí đặt bởi GPS"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"Tắt thông báo"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"Chạm vào đây để bật lại thông báo."</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 8678b6c..108febf 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Cài đặt"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Chế độ trên máy bay"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Khóa hướng màn hình"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TẮT TIẾNG"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"TỰ ĐỘNG"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Thông báo"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth được dùng làm điểm truy cập Internet"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Định cấu hình phương pháp nhập liệu"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Sử dụng bàn phím vật lý"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml
index 207ebe4..f599dca 100644
--- a/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已连接"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"正在搜索 GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS 设置的位置"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"通知已关闭"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"点按此处可以重新打开通知。"</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index c8753f1..5a74abc 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飞行模式"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"锁定屏幕浏览模式"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"静音"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自动"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"蓝牙已绑定"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"配置输入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用物理键盘"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml
index 14a10f2..2191db7 100644
--- a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml
@@ -24,6 +24,8 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已連線"</string>
     <string name="gps_notification_searching_text" msgid="894185519046488403">"正在搜尋 GPS"</string>
     <string name="gps_notification_found_text" msgid="5306445324124275852">"GPS 已定位"</string>
-    <string name="notifications_off_title" msgid="2297252328026582111">"關閉通知"</string>
-    <string name="notifications_off_text" msgid="3754847213329718358">"輕觸這裡即可重新開啟通知。"</string>
+    <!-- no translation found for notifications_off_title (2297252328026582111) -->
+    <skip />
+    <!-- no translation found for notifications_off_text (3754847213329718358) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 3ab5bcf..7509357 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -34,8 +34,7 @@
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飛行模式"</string>
-    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
-    <skip />
+    <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"鎖定螢幕瀏覽模式"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"關閉"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自動"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
@@ -45,8 +44,4 @@
     <string name="bluetooth_tethered" msgid="7094101612161133267">"已透過藍牙進行網際網路共用"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"設定輸入方式"</string>
     <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用實體鍵盤"</string>
-    <!-- no translation found for usb_device_permission_prompt (5340926456453429244) -->
-    <skip />
-    <!-- no translation found for usb_accessory_permission_prompt (3969745913539898765) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 0273a4c..826ac92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -246,6 +246,16 @@
               R.drawable.stat_sys_data_fully_out_3g,
               R.drawable.stat_sys_data_fully_inandout_3g }
         };
+    private static final int[][] sDataNetType_4g = {
+            { R.drawable.stat_sys_data_connected_4g,
+              R.drawable.stat_sys_data_in_4g,
+              R.drawable.stat_sys_data_out_4g,
+              R.drawable.stat_sys_data_inandout_4g },
+            { R.drawable.stat_sys_data_fully_connected_4g,
+              R.drawable.stat_sys_data_fully_in_4g,
+              R.drawable.stat_sys_data_fully_out_4g,
+              R.drawable.stat_sys_data_fully_inandout_4g }
+        };
     private static final int[][] sDataNetType_e = {
             { R.drawable.stat_sys_data_connected_e,
               R.drawable.stat_sys_data_in_e,
@@ -670,9 +680,12 @@
         case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
         case TelephonyManager.NETWORK_TYPE_EVDO_A:
         case TelephonyManager.NETWORK_TYPE_EVDO_B:
+        case TelephonyManager.NETWORK_TYPE_EHRPD:
             mDataIconList = sDataNetType_3g[mInetCondition];
             break;
-        // TODO - add support for NETWORK_TYPE_LTE and NETWORK_TYPE_EHRPD
+        case TelephonyManager.NETWORK_TYPE_LTE:
+            mDataIconList = sDataNetType_4g[mInetCondition];
+            break;
         default:
             mDataIconList = sDataNetType_g[mInetCondition];
         break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 69585ab..6b9551b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -427,10 +427,14 @@
             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
             case TelephonyManager.NETWORK_TYPE_EVDO_A:
             case TelephonyManager.NETWORK_TYPE_EVDO_B:
+            case TelephonyManager.NETWORK_TYPE_EHRPD:
                 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_3g;
                 break;
-            // TODO - add support for NETWORK_TYPE_LTE and NETWORK_TYPE_EHRPD
+            case TelephonyManager.NETWORK_TYPE_LTE:
+                mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
+                mDataTypeIconId = R.drawable.stat_sys_signal_4g;
+                break;
             default:
                 mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_gprs;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 29d35e3..9093b3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -124,5 +124,18 @@
               R.drawable.stat_sys_data_fully_inandout_1x }
             };
 
+    // LTE and eHRPD
+    static final int[][] DATA_4G = {
+            { R.drawable.stat_sys_data_connected_4g,
+              R.drawable.stat_sys_data_in_4g,
+              R.drawable.stat_sys_data_out_4g,
+              R.drawable.stat_sys_data_inandout_4g },
+            { R.drawable.stat_sys_data_fully_connected_4g,
+              R.drawable.stat_sys_data_fully_in_4g,
+              R.drawable.stat_sys_data_fully_out_4g,
+              R.drawable.stat_sys_data_fully_inandout_4g }
+        };
+
+
 }
 
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 14a6b96..1ab22c0 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -24,6 +24,7 @@
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.DummyDataStateTracker;
+import android.net.EthernetDataTracker;
 import android.net.IConnectivityManager;
 import android.net.LinkProperties;
 import android.net.MobileDataStateTracker;
@@ -420,6 +421,10 @@
                 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
                 mNetTrackers[netType].startMonitoring(context, mHandler);
                 break;
+            case ConnectivityManager.TYPE_ETHERNET:
+                mNetTrackers[netType] = EthernetDataTracker.getInstance();
+                mNetTrackers[netType].startMonitoring(context, mHandler);
+                break;
             default:
                 loge("Trying to create a DataStateTracker for an unknown radio type " +
                         mNetAttributes[netType].mRadio);
@@ -696,15 +701,10 @@
         // TODO - move this into the MobileDataStateTracker
         int usedNetworkType = networkType;
         if(networkType == ConnectivityManager.TYPE_MOBILE) {
-            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
-                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
-            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
-                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
-            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
-                    TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
-                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
-            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
-                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            usedNetworkType = convertFeatureToNetworkType(feature);
+            if (usedNetworkType < 0) {
+                Slog.e(TAG, "Can't match any netTracker!");
+                usedNetworkType = networkType;
             }
         }
         NetworkStateTracker network = mNetTrackers[usedNetworkType];
@@ -848,15 +848,9 @@
             // TODO - move to MobileDataStateTracker
             int usedNetworkType = networkType;
             if (networkType == ConnectivityManager.TYPE_MOBILE) {
-                if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
-                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
-                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
-                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
-                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
-                        TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
-                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
-                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
-                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+                usedNetworkType = convertFeatureToNetworkType(feature);
+                if (usedNetworkType < 0) {
+                    usedNetworkType = networkType;
                 }
             }
             tracker =  mNetTrackers[usedNetworkType];
@@ -2174,4 +2168,24 @@
     private void loge(String s) {
         Slog.e(TAG, s);
     }
+    int convertFeatureToNetworkType(String feature){
+        int networkType = -1;
+        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_MMS;
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
+                TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_DUN;
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_IMS;
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
+            networkType = ConnectivityManager.TYPE_MOBILE_CBS;
+        }
+        return networkType;
+    }
 }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 3c6c427..d48cf5a 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -235,6 +235,15 @@
                     }
                     break;
                 }
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+                    if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
+                        Slog.d(TAG, "Send failed, client connection lost");
+                    } else {
+                        Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+                    }
+                    mClients.remove((AsyncChannel) msg.obj);
+                    break;
+                }
                 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
                     AsyncChannel ac = new AsyncChannel();
                     ac.connect(mContext, this, msg.replyTo);
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
index e64ec4e..1f80242 100644
--- a/services/jni/com_android_server_InputApplication.cpp
+++ b/services/jni/com_android_server_InputApplication.cpp
@@ -26,8 +26,6 @@
 namespace android {
 
 static struct {
-    jclass clazz;
-
     jfieldID inputApplicationHandle;
     jfieldID name;
     jfieldID dispatchingTimeoutNanos;
@@ -69,25 +67,25 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_InputApplication(JNIEnv* env) {
-    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/wm/InputApplication");
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/wm/InputApplication");
 
     GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
-            gInputApplicationClassInfo.clazz,
+            clazz,
             "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
 
-    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
+    GET_FIELD_ID(gInputApplicationClassInfo.name, clazz,
             "name", "Ljava/lang/String;");
 
     GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
-            gInputApplicationClassInfo.clazz,
+            clazz,
             "dispatchingTimeoutNanos", "J");
     return 0;
 }
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
index 3a1214f..9516964 100644
--- a/services/jni/com_android_server_InputApplicationHandle.cpp
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -26,8 +26,6 @@
 namespace android {
 
 static struct {
-    jclass clazz;
-
     jfieldID ptr;
 } gInputApplicationHandleClassInfo;
 
@@ -98,8 +96,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
@@ -110,9 +107,10 @@
             gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
-    FIND_CLASS(gInputApplicationHandleClassInfo.clazz, "com/android/server/wm/InputApplicationHandle");
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/wm/InputApplicationHandle");
 
-    GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, gInputApplicationHandleClassInfo.clazz,
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
             "ptr", "I");
 
     return 0;
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 80dddc2..31d0732 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -52,8 +52,6 @@
 namespace android {
 
 static struct {
-    jclass clazz;
-
     jmethodID notifyConfigurationChanged;
     jmethodID notifyLidSwitchChanged;
     jmethodID notifyInputChannelBroken;
@@ -95,16 +93,12 @@
 } gInputDeviceClassInfo;
 
 static struct {
-    jclass clazz;
-
     jfieldID touchscreen;
     jfieldID keyboard;
     jfieldID navigation;
 } gConfigurationClassInfo;
 
 static struct {
-    jclass clazz;
-
     jfieldID bitmap;
     jfieldID hotSpotX;
     jfieldID hotSpotY;
@@ -1226,8 +1220,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
         var = env->GetMethodID(clazz, methodName, methodDescriptor); \
@@ -1244,77 +1237,82 @@
 
     // Callbacks
 
-    FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/wm/InputManager$Callbacks");
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/wm/InputManager$Callbacks");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, clazz,
             "notifyConfigurationChanged", "(J)V");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, clazz,
             "notifyLidSwitchChanged", "(JZ)V");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, clazz,
             "notifyInputChannelBroken", "(Lcom/android/server/wm/InputWindowHandle;)V");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.notifyANR, clazz,
             "notifyANR",
             "(Lcom/android/server/wm/InputApplicationHandle;Lcom/android/server/wm/InputWindowHandle;)J");
 
-    GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
-            gCallbacksClassInfo.clazz,
+            clazz,
             "interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, clazz,
             "interceptKeyBeforeDispatching",
             "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, clazz,
             "dispatchUnhandledKey",
             "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
-    GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, clazz,
             "checkInjectEventsPermission", "(II)Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, clazz,
             "filterTouchEvents", "()Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, clazz,
             "filterJumpyTouchEvents", "()Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyQuietTimeMillis, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyQuietTimeMillis, clazz,
             "getVirtualKeyQuietTimeMillis", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, clazz,
             "getExcludedDeviceNames", "()[Ljava/lang/String;");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatTimeout, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatTimeout, clazz,
             "getKeyRepeatTimeout", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, clazz,
             "getKeyRepeatDelay", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, clazz,
             "getMaxEventsPerSecond", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getPointerLayer, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getPointerLayer, clazz,
             "getPointerLayer", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
+    GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, clazz,
             "getPointerIcon", "()Lcom/android/server/wm/InputManager$PointerIcon;");
 
     // KeyEvent
 
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
+    gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
+
 
     // MotionEvent
 
     FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
+    gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
 
     // InputDevice
 
     FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
+    gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
 
     GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
             "<init>", "()V");
@@ -1336,28 +1334,28 @@
 
     // Configuration
 
-    FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration");
+    FIND_CLASS(clazz, "android/content/res/Configuration");
 
-    GET_FIELD_ID(gConfigurationClassInfo.touchscreen, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.touchscreen, clazz,
             "touchscreen", "I");
 
-    GET_FIELD_ID(gConfigurationClassInfo.keyboard, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.keyboard, clazz,
             "keyboard", "I");
 
-    GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
+    GET_FIELD_ID(gConfigurationClassInfo.navigation, clazz,
             "navigation", "I");
 
     // PointerIcon
 
-    FIND_CLASS(gPointerIconClassInfo.clazz, "com/android/server/wm/InputManager$PointerIcon");
+    FIND_CLASS(clazz, "com/android/server/wm/InputManager$PointerIcon");
 
-    GET_FIELD_ID(gPointerIconClassInfo.bitmap, gPointerIconClassInfo.clazz,
+    GET_FIELD_ID(gPointerIconClassInfo.bitmap, clazz,
             "bitmap", "Landroid/graphics/Bitmap;");
 
-    GET_FIELD_ID(gPointerIconClassInfo.hotSpotX, gPointerIconClassInfo.clazz,
+    GET_FIELD_ID(gPointerIconClassInfo.hotSpotX, clazz,
             "hotSpotX", "F");
 
-    GET_FIELD_ID(gPointerIconClassInfo.hotSpotY, gPointerIconClassInfo.clazz,
+    GET_FIELD_ID(gPointerIconClassInfo.hotSpotY, clazz,
             "hotSpotY", "F");
 
     return 0;
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
index 8548b47..99f625c 100644
--- a/services/jni/com_android_server_InputWindow.cpp
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -28,8 +28,6 @@
 namespace android {
 
 static struct {
-    jclass clazz;
-
     jfieldID inputWindowHandle;
     jfieldID inputChannel;
     jfieldID name;
@@ -136,71 +134,71 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_InputWindow(JNIEnv* env) {
-    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/wm/InputWindow");
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/wm/InputWindow");
 
-    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, clazz,
             "inputWindowHandle", "Lcom/android/server/wm/InputWindowHandle;");
 
-    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, clazz,
             "inputChannel", "Landroid/view/InputChannel;");
 
-    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.name, clazz,
             "name", "Ljava/lang/String;");
 
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, clazz,
             "layoutParamsFlags", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, clazz,
             "layoutParamsType", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, clazz,
             "dispatchingTimeoutNanos", "J");
 
-    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, clazz,
             "frameLeft", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.frameTop, clazz,
             "frameTop", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.frameRight, clazz,
             "frameRight", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, clazz,
             "frameBottom", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, clazz,
             "touchableRegion", "Landroid/graphics/Region;");
 
-    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.visible, clazz,
             "visible", "Z");
 
-    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, clazz,
             "canReceiveKeys", "Z");
 
-    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, clazz,
             "hasFocus", "Z");
 
-    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, clazz,
             "hasWallpaper", "Z");
 
-    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.paused, clazz,
             "paused", "Z");
 
-    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.layer, clazz,
             "layer", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, clazz,
             "ownerPid", "I");
 
-    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, clazz,
             "ownerUid", "I");
     return 0;
 }
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
index 5b74e43..aaf679c 100644
--- a/services/jni/com_android_server_InputWindowHandle.cpp
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -27,8 +27,6 @@
 namespace android {
 
 static struct {
-    jclass clazz;
-
     jfieldID ptr;
     jfieldID inputApplicationHandle;
 } gInputWindowHandleClassInfo;
@@ -108,8 +106,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
@@ -120,13 +117,14 @@
             gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
-    FIND_CLASS(gInputWindowHandleClassInfo.clazz, "com/android/server/wm/InputWindowHandle");
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/wm/InputWindowHandle");
 
-    GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, gInputWindowHandleClassInfo.clazz,
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz,
             "ptr", "I");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
-            gInputWindowHandleClassInfo.clazz,
+            clazz,
             "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
 
     return 0;
diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp
index 705be60..a389c11 100644
--- a/services/jni/com_android_server_PowerManagerService.cpp
+++ b/services/jni/com_android_server_PowerManagerService.cpp
@@ -35,8 +35,6 @@
 // ----------------------------------------------------------------------------
 
 static struct {
-    jclass clazz;
-
     jmethodID goToSleep;
     jmethodID userActivity;
 } gPowerManagerServiceClassInfo;
@@ -144,8 +142,7 @@
 
 #define FIND_CLASS(var, className) \
         var = env->FindClass(className); \
-        LOG_FATAL_IF(! var, "Unable to find class " className); \
-        var = jclass(env->NewGlobalRef(var));
+        LOG_FATAL_IF(! var, "Unable to find class " className);
 
 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
         var = env->GetMethodID(clazz, methodName, methodDescriptor); \
@@ -162,12 +159,13 @@
 
     // Callbacks
 
-    FIND_CLASS(gPowerManagerServiceClassInfo.clazz, "com/android/server/PowerManagerService");
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/PowerManagerService");
 
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, gPowerManagerServiceClassInfo.clazz,
+    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, clazz,
             "goToSleep", "(J)V");
 
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, gPowerManagerServiceClassInfo.clazz,
+    GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, clazz,
             "userActivity", "(JZIZ)V");
 
     // Initialize
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 290f2c1..ba05837 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -91,6 +91,12 @@
     public static final int RADIO_TECHNOLOGY_HSPA = 11;
     /** @hide */
     public static final int RADIO_TECHNOLOGY_EVDO_B = 12;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EHRPD = 13;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_LTE = 14;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_HSPAP = 15;
 
     /**
      * Available registration states for GSM, UMTS and CDMA.
@@ -424,6 +430,15 @@
         case 12:
             radioTechnology = "EvDo rev. B";
             break;
+        case 13:
+            radioTechnology = "eHRPD";
+            break;
+        case 14:
+            radioTechnology = "LTE";
+            break;
+        case 15:
+            radioTechnology = "HSPAP";
+            break;
         default:
             Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
         break;
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
new file mode 100644
index 0000000..bd1bc1d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+
+import android.util.Log;
+import java.util.ArrayList;
+import com.android.internal.telephony.gsm.GsmDataConnection;
+
+/**
+ * Maintain the Apn context
+ */
+public class ApnContext {
+
+    public static final int PENDING_ACTION_NONE = 1;
+    public static final int PENDING_ACTION_RECONNECT = 2;
+    public static final int PENDING_ACTION_APN_DISABLE = 3;
+    public final String LOG_TAG;
+
+    int pendingAction;
+
+    protected static final boolean DBG = true;
+
+    String mApnType;
+
+    DataConnectionTracker.State mState;
+
+    ArrayList<ApnSetting> mWaitingApns = null;
+
+    private int mWaitingApnsPermanentFailureCountDown = 0;
+
+    ApnSetting mApnSetting;
+
+    GsmDataConnection mDataConnection;
+
+    String mReason;
+
+    PendingIntent mReconnectIntent;
+
+    public ApnContext(String apnType, String logTag) {
+        mApnType = apnType;
+        mState = DataConnectionTracker.State.IDLE;
+        setReason(Phone.REASON_DATA_ENABLED);
+        pendingAction = PENDING_ACTION_NONE;
+        LOG_TAG = logTag;
+    }
+
+    public int getPendingAction() {
+        return pendingAction;
+    }
+
+    public void setPendingAction(int pa) {
+        pendingAction = pa;
+    }
+
+    public int getPermFailCount() {
+        return mWaitingApnsPermanentFailureCountDown;
+    }
+
+    public void decPermFailCount() {
+        mWaitingApnsPermanentFailureCountDown--;
+    }
+
+    public String getApnType() {
+        return mApnType;
+    }
+
+    public GsmDataConnection getDataConnection() {
+        return mDataConnection;
+    }
+
+    public void setDataConnection(GsmDataConnection dataConnection) {
+        mDataConnection = dataConnection;
+    }
+
+    public ApnSetting getApnSetting() {
+        return mApnSetting;
+    }
+
+    public void setApnSetting(ApnSetting apnSetting) {
+        mApnSetting = apnSetting;
+    }
+
+    public void setWaitingApns(ArrayList<ApnSetting> waitingApns) {
+        mWaitingApns = waitingApns;
+    }
+
+    public ApnSetting getNextApn() {
+        ArrayList<ApnSetting> list = mWaitingApns;
+        ApnSetting apn = null;
+
+        if (list != null) {
+            if (!list.isEmpty()) {
+                apn = list.get(0);
+            }
+        }
+        return apn;
+    }
+
+    public void removeNextApn() {
+        if ((mWaitingApns != null) && (!mWaitingApns.isEmpty())) {
+            mWaitingApns.remove(0);
+        }
+    }
+
+    public ArrayList<ApnSetting> getWaitingApns() {
+        return mWaitingApns;
+    }
+
+    public void setState(DataConnectionTracker.State s) {
+        if (DBG)
+            log("setState: " + s + " for type " + mApnType + ", previous state:" + mState);
+
+        mState = s;
+
+        if (mState == DataConnectionTracker.State.FAILED) {
+            if (mWaitingApns != null)
+                mWaitingApns.clear(); // when teardown the connection and set to IDLE
+        }
+    }
+
+    public DataConnectionTracker.State getState() {
+        return mState;
+    }
+
+    public void setReason(String reason) {
+        if (DBG)
+            log("set reason as " + reason + ", for type " + mApnType + ",current state " + mState);
+        mReason = reason;
+    }
+
+    public String getReason() {
+        return mReason;
+    }
+
+    public void setReconnectIntent(PendingIntent intent) {
+        if (DBG)
+            log("set ReconnectIntent for type " + mApnType);
+        mReconnectIntent = intent;
+    }
+
+    public PendingIntent getReconnectIntent() {
+        return mReconnectIntent;
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[ApnContext] " + s);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 9b19600..0fc81b0 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -34,6 +34,9 @@
     //***** Instance Variables
     protected Context mContext;
     protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
+    protected RadioState mSimState = RadioState.RADIO_UNAVAILABLE;
+    protected RadioState mRuimState = RadioState.RADIO_UNAVAILABLE;
+    protected RadioState mNvState = RadioState.RADIO_UNAVAILABLE;
     protected Object mStateMonitor = new Object();
 
     protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
@@ -105,6 +108,18 @@
         return mState;
     }
 
+    public RadioState getSimState() {
+        return mSimState;
+    }
+
+    public RadioState getRuimState() {
+        return mRuimState;
+    }
+
+    public RadioState getNvState() {
+        return mNvState;
+    }
+
 
     public void registerForRadioStateChanged(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
@@ -200,7 +215,7 @@
         synchronized (mStateMonitor) {
             mSIMReadyRegistrants.add(r);
 
-            if (mState.isSIMReady()) {
+            if (mSimState.isSIMReady()) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -219,7 +234,7 @@
         synchronized (mStateMonitor) {
             mRUIMReadyRegistrants.add(r);
 
-            if (mState.isRUIMReady()) {
+            if (mRuimState.isRUIMReady()) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -238,7 +253,7 @@
         synchronized (mStateMonitor) {
             mNVReadyRegistrants.add(r);
 
-            if (mState.isNVReady()) {
+            if (mNvState.isNVReady()) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -256,7 +271,7 @@
         synchronized (mStateMonitor) {
             mSIMLockedRegistrants.add(r);
 
-            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+            if (mSimState == RadioState.SIM_LOCKED_OR_ABSENT) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -274,7 +289,7 @@
         synchronized (mStateMonitor) {
             mRUIMLockedRegistrants.add(r);
 
-            if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+            if (mRuimState == RadioState.RUIM_LOCKED_OR_ABSENT) {
                 r.notifyRegistrant(new AsyncResult(null, null, null));
             }
         }
@@ -653,6 +668,22 @@
                 return;
             }
 
+            // FIXME: Use Constants or Enums
+            if(mState.getType() == 0) {
+                mSimState = mState;
+                mRuimState = mState;
+                mNvState = mState;
+            }
+            else if (mState.getType() == 1) {
+                mSimState = mState;
+            }
+            else if (mState.getType() == 2) {
+                mRuimState = mState;
+            }
+            else if (mState.getType() == 3) {
+                mNvState = mState;
+            }
+
             mRadioStateChangedRegistrants.notifyRegistrants();
 
             if (mState.isAvailable() && !oldState.isAvailable()) {
diff --git a/telephony/java/com/android/internal/telephony/CallTracker.java b/telephony/java/com/android/internal/telephony/CallTracker.java
index 9619a66..31f9e18 100644
--- a/telephony/java/com/android/internal/telephony/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/CallTracker.java
@@ -119,6 +119,10 @@
 
     //***** Overridden from Handler
     public abstract void handleMessage (Message msg);
+    public abstract void registerForVoiceCallStarted(Handler h, int what, Object obj);
+    public abstract void unregisterForVoiceCallStarted(Handler h);
+    public abstract void registerForVoiceCallEnded(Handler h, int what, Object obj);
+    public abstract void unregisterForVoiceCallEnded(Handler h);
 
     protected abstract void log(String msg);
 
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index ad21a18..9e1e0c6 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -20,25 +20,28 @@
 
 import android.os.Message;
 import android.os.Handler;
+import android.os.SystemProperties;
 
 
 /**
  * {@hide}
  */
 public interface CommandsInterface {
+    static final boolean LTE_AVAILABLE_ON_CDMA =
+        SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false);
     enum RadioState {
-        RADIO_OFF,         /* Radio explicitly powered off (e.g. CFUN=0) */
-        RADIO_UNAVAILABLE, /* Radio unavailable (e.g. resetting or not booted) */
-        SIM_NOT_READY,     /* Radio is on, but the SIM interface is not ready */
-        SIM_LOCKED_OR_ABSENT,  /* SIM PIN locked, PUK required, network
-                               personalization, or SIM absent */
-        SIM_READY,         /* Radio is on and SIM interface is available */
-        RUIM_NOT_READY,    /* Radio is on, but the RUIM interface is not ready */
-        RUIM_READY,        /* Radio is on and the RUIM interface is available */
-        RUIM_LOCKED_OR_ABSENT, /* RUIM PIN locked, PUK required, network
-                                  personalization locked, or RUIM absent */
-        NV_NOT_READY,      /* Radio is on, but the NV interface is not available */
-        NV_READY;          /* Radio is on and the NV interface is available */
+        RADIO_OFF(0),         /* Radio explictly powered off (eg CFUN=0) */
+        RADIO_UNAVAILABLE(0), /* Radio unavailable (eg, resetting or not booted) */
+        SIM_NOT_READY(1),     /* Radio is on, but the SIM interface is not ready */
+        SIM_LOCKED_OR_ABSENT(1),  /* SIM PIN locked, PUK required, network
+                                     personalization, or SIM absent */
+        SIM_READY(1),         /* Radio is on and SIM interface is available */
+        RUIM_NOT_READY(2),    /* Radio is on, but the RUIM interface is not ready */
+        RUIM_READY(2),        /* Radio is on and the RUIM interface is available */
+        RUIM_LOCKED_OR_ABSENT(2), /* RUIM PIN locked, PUK required, network
+                                     personalization locked, or RUIM absent */
+        NV_NOT_READY(3),      /* Radio is on, but the NV interface is not available */
+        NV_READY(3);          /* Radio is on and the NV interface is available */
 
         public boolean isOn() /* and available...*/ {
             return this == SIM_NOT_READY
@@ -50,6 +53,14 @@
                     || this == NV_NOT_READY
                     || this == NV_READY;
         }
+        private int stateType;
+        private RadioState (int type) {
+            stateType = type;
+        }
+
+        public int getType() {
+            return stateType;
+        }
 
         public boolean isAvailable() {
             return this != RADIO_UNAVAILABLE;
@@ -68,17 +79,25 @@
         }
 
         public boolean isGsm() {
-            return this == SIM_NOT_READY
-                    || this == SIM_LOCKED_OR_ABSENT
-                    || this == SIM_READY;
+            if (LTE_AVAILABLE_ON_CDMA) {
+                return false;
+            } else {
+                return this == SIM_NOT_READY
+                        || this == SIM_LOCKED_OR_ABSENT
+                        || this == SIM_READY;
+            }
         }
 
         public boolean isCdma() {
-            return this ==  RUIM_NOT_READY
-                    || this == RUIM_READY
-                    || this == RUIM_LOCKED_OR_ABSENT
-                    || this == NV_NOT_READY
-                    || this == NV_READY;
+            if (LTE_AVAILABLE_ON_CDMA) {
+                return true;
+            } else {
+                return this ==  RUIM_NOT_READY
+                        || this == RUIM_READY
+                        || this == RUIM_LOCKED_OR_ABSENT
+                        || this == NV_NOT_READY
+                        || this == NV_READY;
+            }
         }
     }
 
@@ -153,6 +172,9 @@
     //***** Methods
 
     RadioState getRadioState();
+    RadioState getSimState();
+    RadioState getRuimState();
+    RadioState getNvState();
 
     /**
      * Fires on any RadioState transition
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 89513fd..1f5fc05 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -219,10 +219,8 @@
     protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
 
     //***** Member Variables
-    protected int mId;
     protected int mTag;
     protected PhoneBase phone;
-    protected RetryManager mRetryMgr;
     protected int cid;
     protected LinkProperties mLinkProperties = new LinkProperties();
     protected LinkCapabilities mCapabilities = new LinkCapabilities();
@@ -244,10 +242,11 @@
 
 
    //***** Constructor
-    protected DataConnection(PhoneBase phone, String name, RetryManager rm) {
+    protected DataConnection(PhoneBase phone, String name, int id, RetryManager rm) {
         super(name);
         if (DBG) log("DataConnection constructor E");
         this.phone = phone;
+        mId = id;
         mRetryMgr = rm;
         this.cid = -1;
         clearSettings();
@@ -342,10 +341,88 @@
         clearSettings();
     }
 
-    public RetryManager getRetryMgr() {
-        return mRetryMgr;
+    /*
+     * **************************************************************************
+     * Begin Members and methods owned by DataConnectionTracker but stored
+     * in a DataConnection because there is one per connection.
+     * **************************************************************************
+     */
+
+    /*
+     * The id is owned by DataConnectionTracker.
+     */
+    private int mId;
+
+    /**
+     * Get the DataConnection ID
+     */
+    public int getDataConnectionId() {
+        return mId;
     }
 
+    /*
+     * The retry manager is currently owned by the DataConnectionTracker but is stored
+     * in the DataConnection because there is one per connection. These methods
+     * should only be used by the DataConnectionTracker although someday the retrying
+     * maybe managed by the DataConnection itself and these methods could disappear.
+     */
+    private RetryManager mRetryMgr;
+
+    /**
+     * @return retry manager retryCount
+     */
+    public int getRetryCount() {
+        return mRetryMgr.getRetryCount();
+    }
+
+    /**
+     * @return retry manager retryTimer
+     */
+    public int getRetryTimer() {
+        return mRetryMgr.getRetryTimer();
+    }
+
+    /**
+     * increaseRetryCount of retry manager
+     */
+    public void increaseRetryCount() {
+        mRetryMgr.increaseRetryCount();
+    }
+
+    /**
+     * @return retry manager isRetryNeeded
+     */
+    public boolean isRetryNeeded() {
+        return mRetryMgr.isRetryNeeded();
+    }
+
+    /**
+     * resetRetryCount of retry manager
+     */
+    public void resetRetryCount() {
+        mRetryMgr.resetRetryCount();
+    }
+
+    /**
+     * set retryForeverUsingLasttimeout of retry manager
+     */
+    public void retryForeverUsingLastTimeout() {
+        mRetryMgr.retryForeverUsingLastTimeout();
+    }
+
+    /**
+     * @return retry manager isRetryForever
+     */
+    public boolean isRetryForever() {
+        return mRetryMgr.isRetryForever();
+    }
+
+    /*
+     * **************************************************************************
+     * End members owned by DataConnectionTracker
+     * **************************************************************************
+     */
+
     /**
      * Clear all settings called when entering mInactiveState.
      */
@@ -964,13 +1041,6 @@
     }
 
     /**
-     * Get the DataConnection ID
-     */
-    public int getDataConnectionId() {
-        return mId;
-    }
-
-    /**
      * Return the LinkProperties for the connection.
      *
      * @return a copy of the LinkProperties, is never null.
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 7f8485b..0b10727 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -97,14 +97,14 @@
     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
     protected static final int EVENT_VOICE_CALL_STARTED = 14;
     protected static final int EVENT_VOICE_CALL_ENDED = 15;
-    protected static final int EVENT_GPRS_DETACHED = 19;
+    protected static final int EVENT_DATA_CONNECTION_DETACHED = 19;
     protected static final int EVENT_LINK_STATE_CHANGED = 20;
     protected static final int EVENT_ROAMING_ON = 21;
     protected static final int EVENT_ROAMING_OFF = 22;
     protected static final int EVENT_ENABLE_NEW_APN = 23;
     protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
     protected static final int EVENT_DISCONNECT_DONE = 25;
-    protected static final int EVENT_GPRS_ATTACHED = 26;
+    protected static final int EVENT_DATA_CONNECTION_ATTACHED = 26;
     protected static final int EVENT_START_NETSTAT_POLL = 27;
     protected static final int EVENT_START_RECOVERY = 28;
     protected static final int EVENT_APN_CHANGED = 29;
@@ -117,8 +117,8 @@
     protected static final int EVENT_RESTART_RADIO = 36;
     protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37;
     protected static final int EVENT_RESET_DONE = 38;
-
     public static final int CMD_SET_DATA_ENABLE = 39;
+    public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = 40;
 
     /***** Constants *****/
 
@@ -128,7 +128,10 @@
     protected static final int APN_SUPL_ID = 2;
     protected static final int APN_DUN_ID = 3;
     protected static final int APN_HIPRI_ID = 4;
-    protected static final int APN_NUM_TYPES = 5;
+    protected static final int APN_IMS_ID = 5;
+    protected static final int APN_FOTA_ID = 6;
+    protected static final int APN_CBS_ID = 7;
+    protected static final int APN_NUM_TYPES = 8;
 
     public static final int DISABLED = 0;
     public static final int ENABLED = 1;
@@ -206,9 +209,6 @@
     protected int mNoRecvPollCount = 0;
     protected boolean mNetStatPollEnabled = false;
 
-    /** Manage the behavior of data retry after failure (TODO: One per connection in the future?) */
-    protected RetryManager mRetryMgr = new RetryManager();
-
     // wifi connection status will be updated by sticky intent
     protected boolean mIsWifiConnected = false;
 
@@ -261,15 +261,8 @@
                 startNetStatPoll();
             } else if (action.equals(getActionIntentReconnectAlarm())) {
                 log("Reconnect alarm. Previous state was " + mState);
+                onActionIntentReconnectAlarm(intent);
 
-                String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
-                if (mState == State.FAILED) {
-                    Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
-                    msg.arg1 = 0; // tearDown is false
-                    msg.obj = reason;
-                    sendMessage(msg);
-                }
-                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 final android.net.NetworkInfo networkInfo = (NetworkInfo)
                         intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
@@ -287,6 +280,18 @@
         }
     };
 
+    protected void onActionIntentReconnectAlarm(Intent intent) {
+        String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+        if (mState == State.FAILED) {
+            Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+            msg.arg1 = 0; // tearDown is false
+            msg.arg2 = 0;
+            msg.obj = reason;
+            sendMessage(msg);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+    }
+
     /**
      * Default constructor
      */
@@ -334,22 +339,10 @@
     }
 
     public State getState() {
+        // TODO: reimplement to use apnType better yet REMOVE.
         return mState;
     }
 
-    public String getStateInString() {
-        switch (mState) {
-            case IDLE:          return "IDLE";
-            case INITING:       return "INIT";
-            case CONNECTING:    return "CING";
-            case SCANNING:      return "SCAN";
-            case CONNECTED:     return "CNTD";
-            case DISCONNECTING: return "DING";
-            case FAILED:        return "FAIL";
-            default:            return "ERRO";
-        }
-    }
-
     /**
      * @return the data connections
      */
@@ -374,7 +367,7 @@
         return result;
     }
 
-    public String getActiveApnType() {
+    private String getActiveApnType() {
         String result;
         if (mActiveApn != null) {
             result = apnIdToType(mActiveApn.id);
@@ -384,7 +377,7 @@
         return result;
     }
 
-    protected String getActiveApnString() {
+    public String getActiveApnString() {
         String result = null;
         if (mActiveApn != null) {
             result = mActiveApn.apn;
@@ -392,17 +385,6 @@
         return result;
     }
 
-    /**
-     * The data connection is expected to be setup while device
-     *  1. has Icc card
-     *  2. registered for data service
-     *  3. user doesn't explicitly disable data service
-     *  4. wifi is not on
-     *
-     * @return false while no data connection if all above requirements are met.
-     */
-    public abstract boolean isDataConnectionAsDesired();
-
     //The data roaming setting is now located in the shared preferences.
     //  See if the requested preference value is the same as that stored in
     //  the shared values.  If it is not, then update it.
@@ -412,7 +394,7 @@
                 Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
             if (mPhone.getServiceState().getRoaming()) {
                 if (enabled) {
-                    mRetryMgr.resetRetryCount();
+                    resetAllRetryCounts();
                 }
                 sendMessage(obtainMessage(EVENT_ROAMING_ON));
             }
@@ -443,7 +425,8 @@
     protected abstract void onResetDone(AsyncResult ar);
     protected abstract void onVoiceCallStarted();
     protected abstract void onVoiceCallEnded();
-    protected abstract void onCleanUpConnection(boolean tearDown, String reason);
+    protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason);
+    protected abstract void onCleanUpAllConnections();
 
     @Override
     public void handleMessage(Message msg) {
@@ -463,7 +446,7 @@
 
             case EVENT_ROAMING_OFF:
                 if (getDataOnRoamingEnabled() == false) {
-                    mRetryMgr.resetRetryCount();
+                    resetAllRetryCounts();
                 }
                 onRoamingOff();
                 break;
@@ -498,11 +481,15 @@
                 onVoiceCallEnded();
                 break;
 
-            case EVENT_CLEAN_UP_CONNECTION:
-                boolean tearDown = (msg.arg1 == 0) ? false : true;
-                onCleanUpConnection(tearDown, (String) msg.obj);
+            case EVENT_CLEAN_UP_ALL_CONNECTIONS: {
+                onCleanUpAllConnections();
                 break;
-
+            }
+            case EVENT_CLEAN_UP_CONNECTION: {
+                boolean tearDown = (msg.arg1 == 0) ? false : true;
+                onCleanUpConnection(tearDown, msg.arg2, (String) msg.obj);
+                break;
+            }
             case EVENT_SET_INTERNAL_DATA_ENABLE: {
                 boolean enabled = (msg.arg1 == ENABLED) ? true : false;
                 onSetInternalDataEnabled(enabled);
@@ -557,6 +544,12 @@
             return APN_DUN_ID;
         } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
             return APN_HIPRI_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_IMS)) {
+            return APN_IMS_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_FOTA)) {
+            return APN_FOTA_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_CBS)) {
+            return APN_CBS_ID;
         } else {
             return APN_INVALID_ID;
         }
@@ -574,6 +567,12 @@
             return Phone.APN_TYPE_DUN;
         case APN_HIPRI_ID:
             return Phone.APN_TYPE_HIPRI;
+        case APN_IMS_ID:
+            return Phone.APN_TYPE_IMS;
+        case APN_FOTA_ID:
+            return Phone.APN_TYPE_FOTA;
+        case APN_CBS_ID:
+            return Phone.APN_TYPE_CBS;
         default:
             log("Unknown id (" + id + ") in apnIdToType");
             return Phone.APN_TYPE_DEFAULT;
@@ -826,7 +825,7 @@
                 dataEnabled[apnId] = false;
                 enabledCount--;
                 if (enabledCount == 0) {
-                    onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+                    onCleanUpConnection(true, apnId, Phone.REASON_DATA_DISABLED);
                 }
 
                 // send the disconnect msg manually, since the normal route wont send
@@ -881,10 +880,10 @@
             }
             if (prevEnabled != getAnyDataEnabled()) {
                 if (!prevEnabled) {
-                    mRetryMgr.resetRetryCount();
+                    resetAllRetryCounts();
                     onTrySetupData(Phone.REASON_DATA_ENABLED);
                 } else {
-                    onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+                    cleanUpAllConnections();
                 }
             }
         }
@@ -894,6 +893,17 @@
         return mDataEnabled;
     }
 
+    public void cleanUpAllConnections() {
+        Message msg = obtainMessage(EVENT_CLEAN_UP_ALL_CONNECTIONS);
+        sendMessage(msg);
+    }
+
+    public boolean isAnyActiveDataConnections() {
+        // TODO: Remember if there are any connected or
+        // loop asking each DC/APN?
+        return true;
+    }
+
     protected void onSetDataEnabled(boolean enable) {
         boolean prevEnabled = getAnyDataEnabled();
         if (mDataEnabled != enable) {
@@ -904,12 +914,18 @@
                     Settings.Secure.MOBILE_DATA, enable ? 1 : 0);
             if (prevEnabled != getAnyDataEnabled()) {
                 if (!prevEnabled) {
-                    mRetryMgr.resetRetryCount();
+                    resetAllRetryCounts();
                     onTrySetupData(Phone.REASON_DATA_ENABLED);
                 } else {
-                    onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+                    onCleanUpConnection(true, APN_DEFAULT_ID, Phone.REASON_DATA_DISABLED);
                 }
             }
         }
     }
+
+    protected void resetAllRetryCounts() {
+        for (DataConnection dc : mDataConnections.values()) {
+            dc.resetRetryCount();
+        }
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index e270ce9..dbfc0d4 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -28,6 +28,7 @@
 
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.CommandsInterface.RadioState;
+import android.os.SystemProperties;
 
 /**
  * {@hide}
@@ -85,6 +86,9 @@
     private static final int EVENT_QUERY_FACILITY_FDN_DONE = 10;
     private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 11;
 
+    static final boolean LTE_AVAILABLE_ON_CDMA =
+            SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false);
+
     /*
       UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
       PIN_REQUIRED state, the query for ICC status returns UNKNOWN before it
@@ -426,6 +430,9 @@
             broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED,
                   INTENT_VALUE_LOCKED_NETWORK);
         }
+        if (oldState != State.READY && newState == State.READY && LTE_AVAILABLE_ON_CDMA) {
+            mPhone.mSIMRecords.onSimReady();
+        }
     }
 
     /**
@@ -612,14 +619,16 @@
             currentRadioState == RadioState.SIM_NOT_READY     ||
             currentRadioState == RadioState.RUIM_NOT_READY    ||
             currentRadioState == RadioState.NV_NOT_READY      ||
-            currentRadioState == RadioState.NV_READY) {
+            (currentRadioState == RadioState.NV_READY && !LTE_AVAILABLE_ON_CDMA)) {
             return IccCard.State.NOT_READY;
         }
 
         if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT  ||
             currentRadioState == RadioState.SIM_READY             ||
             currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
-            currentRadioState == RadioState.RUIM_READY) {
+            currentRadioState == RadioState.RUIM_READY ||
+            (currentRadioState == RadioState.NV_READY && LTE_AVAILABLE_ON_CDMA)) {
+
 
             int index;
 
diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java
index 9f60a6c..4cf21ee 100644
--- a/telephony/java/com/android/internal/telephony/IccCardApplication.java
+++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java
@@ -28,7 +28,8 @@
         APPTYPE_SIM,
         APPTYPE_USIM,
         APPTYPE_RUIM,
-        APPTYPE_CSIM
+        APPTYPE_CSIM,
+        APPTYPE_ISIM
     };
 
     public enum AppState{
@@ -115,6 +116,7 @@
             case 2: newType = AppType.APPTYPE_USIM;    break;
             case 3: newType = AppType.APPTYPE_RUIM;    break;
             case 4: newType = AppType.APPTYPE_CSIM;    break;
+            case 5: newType = AppType.APPTYPE_ISIM;    break;
             default:
                 throw new RuntimeException(
                             "Unrecognized RIL_AppType: " +type);
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index b12d2d4..b40f945 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -58,6 +58,13 @@
     static final int EF_CST = 0x6f32;
     static final int EF_RUIM_SPN =0x6F41;
 
+    //ISIM access
+    static final int EF_IMPU = 0x6f04;
+    static final int EF_IMPI = 0x6f02;
+    static final int EF_DOMAIN = 0x6f03;
+    static final int EF_IST = 0x6f07;
+    static final int EF_PCSCF = 0x6f09;
+
     // SMS record length from TS 51.011 10.5.3
     static public final int SMS_RECORD_LENGTH = 176;
 
@@ -67,4 +74,7 @@
     static final String DF_GRAPHICS = "5F50";
     static final String DF_GSM = "7F20";
     static final String DF_CDMA = "7F25";
+
+    //ISIM access
+    static final String DF_ADFISIM = "7FFF";
 }
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index acb86d4..7450047 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -125,6 +125,12 @@
     static final String APN_TYPE_DUN = "dun";
     /** APN type for HiPri traffic */
     static final String APN_TYPE_HIPRI = "hipri";
+    /** APN type for FOTA */
+    static final String APN_TYPE_FOTA = "fota";
+    /** APN type for IMS */
+    static final String APN_TYPE_IMS = "ims";
+    /** APN type for CBS */
+    static final String APN_TYPE_CBS = "cbs";
 
     // "Features" accessible through the connectivity manager
     static final String FEATURE_ENABLE_MMS = "enableMMS";
@@ -132,6 +138,9 @@
     static final String FEATURE_ENABLE_DUN = "enableDUN";
     static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
     static final String FEATURE_ENABLE_DUN_ALWAYS = "enableDUNAlways";
+    static final String FEATURE_ENABLE_FOTA = "enableFOTA";
+    static final String FEATURE_ENABLE_IMS = "enableIMS";
+    static final String FEATURE_ENABLE_CBS = "enableCBS";
 
     /**
      * Return codes for <code>enableApnType()</code>
@@ -140,6 +149,7 @@
     static final int APN_REQUEST_STARTED    = 1;
     static final int APN_TYPE_NOT_AVAILABLE = 2;
     static final int APN_REQUEST_FAILED     = 3;
+    static final int APN_ALREADY_INACTIVE   = 4;
 
 
     /**
@@ -164,6 +174,7 @@
     static final String REASON_PS_RESTRICT_ENABLED = "psRestrictEnabled";
     static final String REASON_PS_RESTRICT_DISABLED = "psRestrictDisabled";
     static final String REASON_SIM_LOADED = "simLoaded";
+    static final String REASON_NW_TYPE_CHANGED = "nwTypeChanged";
 
     // Used for band mode selection methods
     static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
@@ -193,6 +204,7 @@
     int NT_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
     int NT_MODE_GLOBAL       = RILConstants.NETWORK_MODE_GLOBAL;
 
+    int NT_MODE_LTE_ONLY     = RILConstants.NETWORK_MODE_LTE_ONLY;
     int PREFERRED_NT_MODE    = RILConstants.PREFERRED_NETWORK_MODE;
 
 
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 54341b1..5408ce9 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -38,6 +38,8 @@
 
 import com.android.internal.R;
 import com.android.internal.telephony.test.SimulatedRadioControl;
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.gsm.SimCard;
 
 import java.util.Locale;
 
@@ -116,6 +118,9 @@
     int mCallRingDelay;
     public boolean mIsTheCurrentActivePhone = true;
     boolean mIsVoiceCapable = true;
+    public SIMRecords mSIMRecords;
+    public SimCard mSimCard;
+    public SMSDispatcher mSMS;
 
     /**
      * Set a system property, unless we're in unit test mode
@@ -237,7 +242,8 @@
     public void dispose() {
         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
             mCM.unSetOnCallRing(this);
-            mDataConnection.onCleanUpConnection(false, REASON_RADIO_TURNED_OFF);
+            // Must cleanup all connectionS and needs to use sendMessage!
+            mDataConnection.cleanUpAllConnections();
             mIsTheCurrentActivePhone = false;
         }
     }
@@ -662,6 +668,20 @@
     }
 
     /**
+    * Retrieves the ServiceStateTracker of the phone instance.
+    */
+    public ServiceStateTracker getServiceStateTracker() {
+        return null;
+    }
+
+    /**
+    * Get call tracker
+    */
+    public CallTracker getCallTracker() {
+        return null;
+    }
+
+    /**
      *  Query the status of the CDMA roaming preference
      */
     public void queryCdmaRoamingPreference(Message response) {
@@ -1080,4 +1100,14 @@
         Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
                 "called, GSMPhone inactive.");
     }
+
+    // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
+    public void notifyCallForwardingIndicator() {
+        // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void notifyDataConnectionFailed(String reason, String apnType) {
+        mNotifier.notifyDataConnectionFailed(this, reason, apnType);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 2e391cb..ab0bb63 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -21,8 +21,10 @@
 import android.os.Looper;
 import android.provider.Settings;
 import android.util.Log;
+import android.os.SystemProperties;
 
 import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.cdma.CDMALTEPhone;
 import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.sip.SipPhone;
 import com.android.internal.telephony.sip.SipPhoneFactory;
@@ -34,6 +36,9 @@
     static final String LOG_TAG = "PHONE";
     static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
     static final int SOCKET_OPEN_MAX_RETRY = 3;
+    static final boolean LTE_AVAILABLE_ON_CDMA =
+            SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false);
+
     //***** Class Variables
 
     static private Phone sProxyPhone = null;
@@ -115,9 +120,15 @@
                     sProxyPhone = new PhoneProxy(new GSMPhone(context,
                             sCommandsInterface, sPhoneNotifier));
                 } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
-                    Log.i(LOG_TAG, "Creating CDMAPhone");
-                    sProxyPhone = new PhoneProxy(new CDMAPhone(context,
-                            sCommandsInterface, sPhoneNotifier));
+                    if (LTE_AVAILABLE_ON_CDMA == false ) {
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                    } else {
+                        Log.i(LOG_TAG, "Creating CDMALTEPhone");
+                        sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                    }
                 }
 
                 sMadeDefaults = true;
@@ -147,6 +158,14 @@
 
         case RILConstants.NETWORK_MODE_GLOBAL:
             return Phone.PHONE_TYPE_CDMA;
+
+        case RILConstants.NETWORK_MODE_LTE_ONLY:
+            if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA,
+                    false)) {
+                return Phone.PHONE_TYPE_CDMA;
+            } else {
+                return Phone.PHONE_TYPE_GSM;
+            }
         default:
             return Phone.PHONE_TYPE_GSM;
         }
@@ -166,8 +185,13 @@
 
     public static Phone getCdmaPhone() {
         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
-            Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
-            return phone;
+            if (LTE_AVAILABLE_ON_CDMA == false) {
+                Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
+                return phone;
+            } else {
+                Phone phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier);
+                return phone;
+            }
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 15b23bb..49497b4 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -741,6 +741,10 @@
          return mActivePhone.getCdmaEriIconMode();
     }
 
+    public Phone getActivePhone() {
+         return mActivePhone;
+    }
+
     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete){
         mActivePhone.sendBurstDtmf(dtmfString, on, off, onComplete);
     }
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 804ace4..88aed28 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -638,6 +638,14 @@
             case RILConstants.NETWORK_MODE_GLOBAL:
                 mPhoneType = RILConstants.CDMA_PHONE;
                 break;
+            case RILConstants.NETWORK_MODE_LTE_ONLY:
+                if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA,
+                        false)) {
+                    mPhoneType = RILConstants.CDMA_PHONE;
+                } else {
+                    mPhoneType = RILConstants.GSM_PHONE;
+                }
+                break;
             default:
                 mPhoneType = RILConstants.CDMA_PHONE;
         }
@@ -1389,33 +1397,29 @@
         if(mInitialRadioStateChange) {
             synchronized (mStateMonitor) {
                 if (!mState.isOn()) {
-                    RILRequest rrPnt = RILRequest.obtain(
-                                   RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, null);
-
-                    rrPnt.mp.writeInt(1);
-                    rrPnt.mp.writeInt(mNetworkMode);
-                    if (RILJ_LOGD) riljLog(rrPnt.serialString() + "> "
-                        + requestToString(rrPnt.mRequest) + " : " + mNetworkMode);
-
-                    send(rrPnt);
+                    setPreferredNetworkType(mNetworkMode, null);
 
                     RILRequest rrCs = RILRequest.obtain(
                                    RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, null);
                     rrCs.mp.writeInt(1);
                     rrCs.mp.writeInt(mCdmaSubscription);
-                    if (RILJ_LOGD) riljLog(rrCs.serialString() + "> "
-                    + requestToString(rrCs.mRequest) + " : " + mCdmaSubscription);
+                    if (RILJ_LOGD) {
+                        riljLog(rrCs.serialString() + "> "
+                                + requestToString(rrCs.mRequest) + " : " + mCdmaSubscription);
+                    }
                     send(rrCs);
                 }
             }
         }
-        RILRequest rr
-                = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(on ? 1 : 0);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                    + (on ? " on" : " off"));
+        }
 
         send(rr);
     }
@@ -2067,6 +2071,7 @@
             } else {
                 if (DBG) Log.d(LOG_TAG, "Radio OFF @ init");
                 setRadioState(newState);
+                setPreferredNetworkType(mNetworkMode, null);
             }
             mInitialRadioStateChange = false;
         } else {
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index cdf1977..8c9fb79 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -66,6 +66,8 @@
     int NETWORK_MODE_EVDO_NO_CDMA   = 6; /* EvDo only */
     int NETWORK_MODE_GLOBAL         = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
                                             AVAILABLE Application Settings menu*/
+    int NETWORK_MODE_LTE_ONLY       = 8; /* LTE Only mode. Used only for testing purposes.Not
+                                            user selectable from regular UI */
     int PREFERRED_NETWORK_MODE      = NETWORK_MODE_WCDMA_PREF;
 
     /* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
@@ -138,10 +140,12 @@
     int RIL_RESTRICTED_STATE_PS_ALL = 0x10;
 
     /** Data profile for RIL_REQUEST_SETUP_DATA_CALL */
-    static final int DATA_PROFILE_DEFAULT   = 0;
-    static final int DATA_PROFILE_TETHERED  = 1;
-    static final int DATA_PROFILE_OEM_BASE  = 1000;
-
+    public static final int DATA_PROFILE_DEFAULT   = 0;
+    public static final int DATA_PROFILE_TETHERED  = 1;
+    public static final int DATA_PROFILE_IMS       = 2;
+    public static final int DATA_PROFILE_FOTA      = 3;
+    public static final int DATA_PROFILE_CBS       = 4;
+    public static final int DATA_PROFILE_OEM_BASE  = 1000;
 
     int RIL_REQUEST_GET_SIM_STATUS = 1;
     int RIL_REQUEST_ENTER_SIM_PIN = 2;
diff --git a/telephony/java/com/android/internal/telephony/gsm/RestrictedState.java b/telephony/java/com/android/internal/telephony/RestrictedState.java
similarity index 98%
rename from telephony/java/com/android/internal/telephony/gsm/RestrictedState.java
rename to telephony/java/com/android/internal/telephony/RestrictedState.java
index 3f7d5d7..ad2b88d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RestrictedState.java
+++ b/telephony/java/com/android/internal/telephony/RestrictedState.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.telephony.ServiceState;
 
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index befee8c..6af9b1c 100755
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -582,7 +582,7 @@
      *         {@link Activity#RESULT_OK} if the message has been broadcast
      *         to applications
      */
-    protected abstract int dispatchMessage(SmsMessageBase sms);
+    public abstract int dispatchMessage(SmsMessageBase sms);
 
 
     /**
@@ -916,7 +916,7 @@
      * @param response
      *            Callback message is empty on completion
      */
-    protected abstract void activateCellBroadcastSms(int activate, Message response);
+    public abstract void activateCellBroadcastSms(int activate, Message response);
 
     /**
      * Query the current configuration of cell broadcast SMS.
@@ -925,7 +925,7 @@
      *            Callback message contains the configuration from the modem on completion
      *            @see #setCellBroadcastConfig
      */
-    protected abstract void getCellBroadcastSmsConfig(Message response);
+    public abstract void getCellBroadcastSmsConfig(Message response);
 
     /**
      * Configure cell broadcast SMS.
@@ -937,7 +937,7 @@
      * @param response
      *            Callback message is empty on completion
      */
-    protected abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
+    public abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
 
     /**
      * Send an acknowledge message.
@@ -1006,6 +1006,27 @@
         return new SmsTracker(data, sentIntent, deliveryIntent);
     }
 
+    public void initSipStack(boolean isObg) {
+        // This function should be overridden by the classes that support
+        // switching modes such as the CdmaSMSDispatcher.
+        // Not implemented in GsmSMSDispatcher.
+        Log.e(TAG, "Error! This function should never be executed.");
+    }
+
+    public void switchToCdma() {
+        // This function should be overridden by the classes that support
+        // switching modes such as the CdmaSMSDispatcher.
+        // Not implemented in GsmSMSDispatcher.
+        Log.e(TAG, "Error! This function should never be executed.");
+    }
+
+    public void switchToGsm() {
+        // This function should be overridden by the classes that support
+        // switching modes such as the CdmaSMSDispatcher.
+        // Not implemented in GsmSMSDispatcher.
+        Log.e(TAG, "Error! This function should never be executed.");
+    }
+
     private DialogInterface.OnClickListener mListener =
         new DialogInterface.OnClickListener() {
 
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 3f9ffc3..3905415 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -45,6 +45,8 @@
     protected static final int DATA_ACCESS_HSUPA = 10;
     protected static final int DATA_ACCESS_HSPA = 11;
     protected static final int DATA_ACCESS_CDMA_EvDo_B = 12;
+    protected static final int DATA_ACCESS_LTE = 13;
+    protected static final int DATA_ACCESS_EHRPD = 14;
 
     protected CommandsInterface cm;
 
@@ -53,6 +55,9 @@
 
     public SignalStrength mSignalStrength;
 
+    // TODO - this should not be public
+    public RestrictedState mRestrictedState = new RestrictedState();
+
     /* The otaspMode passed to PhoneStateListener#onOtaspChanged */
     static public final int OTASP_UNINITIALIZED = 0;
     static public final int OTASP_UNKNOWN = 1;
@@ -74,9 +79,14 @@
      */
     protected boolean dontPollSignalStrength = false;
 
-    protected RegistrantList networkAttachedRegistrants = new RegistrantList();
-    protected RegistrantList roamingOnRegistrants = new RegistrantList();
-    protected RegistrantList roamingOffRegistrants = new RegistrantList();
+    protected RegistrantList mRoamingOnRegistrants = new RegistrantList();
+    protected RegistrantList mRoamingOffRegistrants = new RegistrantList();
+    protected RegistrantList mAttachedRegistrants = new RegistrantList();
+    protected RegistrantList mDetachedRegistrants = new RegistrantList();
+    protected RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
+    protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
+    protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
+
 
     protected  static final boolean DBG = true;
 
@@ -163,7 +173,6 @@
     protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
 
     public ServiceStateTracker() {
-
     }
 
     public boolean getDesiredPowerState() {
@@ -180,7 +189,7 @@
      */
     public  void registerForRoamingOn(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
-        roamingOnRegistrants.add(r);
+        mRoamingOnRegistrants.add(r);
 
         if (ss.getRoaming()) {
             r.notifyRegistrant();
@@ -188,7 +197,7 @@
     }
 
     public  void unregisterForRoamingOn(Handler h) {
-        roamingOnRegistrants.remove(h);
+        mRoamingOnRegistrants.remove(h);
     }
 
     /**
@@ -201,7 +210,7 @@
      */
     public  void registerForRoamingOff(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
-        roamingOffRegistrants.add(r);
+        mRoamingOffRegistrants.add(r);
 
         if (!ss.getRoaming()) {
             r.notifyRegistrant();
@@ -209,7 +218,7 @@
     }
 
     public  void unregisterForRoamingOff(Handler h) {
-        roamingOffRegistrants.remove(h);
+        mRoamingOffRegistrants.remove(h);
     }
 
     /**
@@ -280,12 +289,107 @@
     protected abstract void setPowerStateToDesired();
     protected abstract void log(String s);
 
+    public abstract int getCurrentDataConnectionState();
+    public abstract boolean isConcurrentVoiceAndDataAllowed();
+
+    /**
+     * Registration point for transition into DataConnection attached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mAttachedRegistrants.add(r);
+
+        if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
+            r.notifyRegistrant();
+        }
+    }
+    public void unregisterForDataConnectionAttached(Handler h) {
+        mAttachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into DataConnection detached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mDetachedRegistrants.add(r);
+
+        if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+            r.notifyRegistrant();
+        }
+    }
+    public void unregisterForDataConnectionDetached(Handler h) {
+        mDetachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into network attached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj in Message.obj
+     */
+    public void registerForNetworkAttached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+
+        mNetworkAttachedRegistrants.add(r);
+        if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+            r.notifyRegistrant();
+        }
+    }
+    public void unregisterForNetworkAttached(Handler h) {
+        mNetworkAttachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into packet service restricted zone.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mPsRestrictEnabledRegistrants.add(r);
+
+        if (mRestrictedState.isPsRestricted()) {
+            r.notifyRegistrant();
+        }
+    }
+
+    public void unregisterForPsRestrictedEnabled(Handler h) {
+        mPsRestrictEnabledRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition out of packet service restricted zone.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mPsRestrictDisabledRegistrants.add(r);
+
+        if (mRestrictedState.isPsRestricted()) {
+            r.notifyRegistrant();
+        }
+    }
+
+    public void unregisterForPsRestrictedDisabled(Handler h) {
+        mPsRestrictDisabledRegistrants.remove(h);
+    }
+
     /**
      * Clean up existing voice and data connection then turn off radio power.
      *
      * Hang up the existing voice calls to decrease call drop rate.
      */
-    protected abstract void powerOffRadioSafely();
+    public abstract void powerOffRadioSafely();
 
     /** Cancel a pending (if any) pollState() operation */
     protected void cancelPollState() {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index e6189be..c4fab66 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -72,6 +72,11 @@
      */
     static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
 
+    /** 'true' if device supports both LTE and CDMA mode of operation.
+     *  Availability: Set only on devices supporting LTE and CDMA.
+     */
+    static final String PROPERTY_NETWORK_LTE_ON_CDMA = "ro.telephony.lte_on_cdma";
+
     static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type";
 
     //****** SIM Card
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
new file mode 100644
index 0000000..89d7174
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.SystemProperties;
+import android.content.Context;
+import android.net.Uri;
+import android.content.Context;
+import android.provider.Telephony;
+import android.content.ContentValues;
+import android.database.SQLException;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.gsm.SimCard;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+import android.util.Log;
+
+public class CDMALTEPhone extends CDMAPhone {
+    static final String LOG_TAG = "CDMA";
+
+    private static final boolean DBG = true;
+
+    // Constructors
+    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
+        this(context, ci, notifier, false);
+        log("CDMALTEPhone Constructors");
+    }
+
+    public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+            boolean unitTestMode) {
+        super(context, ci, notifier, false);
+
+        mSIMRecords = new SIMRecords(this);
+        mSimCard = new SimCard(this, LOG_TAG, DBG);
+    }
+
+    @Override
+    protected void initSST() {
+        mSST = new CdmaLteServiceStateTracker(this);
+    }
+
+    public void dispose() {
+        synchronized (PhoneProxy.lockForRadioTechnologyChange) {
+            super.dispose();
+            mSIMRecords.dispose();
+            mSimCard.dispose();
+        }
+    }
+
+    @Override
+    public void removeReferences() {
+        super.removeReferences();
+        this.mSIMRecords = null;
+        this.mSimCard = null;
+    }
+
+    @Override
+    public ServiceStateTracker getServiceStateTracker() {
+        return mSST;
+    }
+
+    public IccCard getIccCard() {
+        return mSimCard;
+    }
+
+    @Override
+    public String getIccSerialNumber() {
+        return mSIMRecords.iccid;
+    }
+
+    @Override
+    public DataState getDataConnectionState(String apnType) {
+        boolean isCdmaDataConnectionTracker = false;
+        if (mDataConnection instanceof CdmaDataConnectionTracker) {
+            isCdmaDataConnectionTracker = true;
+        }
+        log("getDataConnectionState");
+        DataState ret = DataState.DISCONNECTED;
+
+        if (!isCdmaDataConnectionTracker && (SystemProperties.get("adb.connected", "").length()
+                > 0)) {
+            // We're connected to an ADB host and we have USB networking
+            // turned on. No matter what the radio state is,
+            // we report data connected
+
+            ret = DataState.CONNECTED;
+        } else if (mSST == null) {
+            // Radio Technology Change is ongoning, dispose() and
+            // removeReferences() have
+            // already been called
+
+            ret = DataState.DISCONNECTED;
+        } else if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+            // If we're out of service, open TCP sockets may still work
+            // but no data will flow
+            ret = DataState.DISCONNECTED;
+        } else if (mDataConnection.isApnTypeEnabled(apnType) == false) {
+            ret = DataState.DISCONNECTED;
+        } else {
+            DataConnectionTracker.State state;
+            if (isCdmaDataConnectionTracker) {
+                state = mDataConnection.getState();
+            } else {
+                state = ((GsmDataConnectionTracker)mDataConnection).getState(apnType);
+            }
+            switch (state) {
+                case FAILED:
+                case IDLE:
+                    ret = DataState.DISCONNECTED;
+                    break;
+
+                case CONNECTED:
+                case DISCONNECTING:
+                    if (mCT.state != Phone.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed()) {
+                        ret = DataState.SUSPENDED;
+                    } else {
+                        ret = DataState.CONNECTED;
+                    }
+                    break;
+
+                case INITING:
+                case CONNECTING:
+                case SCANNING:
+                    ret = DataState.CONNECTING;
+                    break;
+            }
+        }
+
+        return ret;
+    }
+
+    public boolean updateCurrentCarrierInProvider() {
+        if (mSIMRecords != null) {
+            try {
+                Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
+                ContentValues map = new ContentValues();
+                map.put(Telephony.Carriers.NUMERIC, mSIMRecords.getSIMOperatorNumeric());
+                mContext.getContentResolver().insert(uri, map);
+                return true;
+            } catch (SQLException e) {
+                Log.e(LOG_TAG, "[CDMALTEPhone] Can't store current operator", e);
+            }
+        }
+        return false;
+    }
+
+    public String getActiveApn(String apnType) {
+        if (mDataConnection instanceof CdmaDataConnectionTracker)
+            return mDataConnection.getActiveApnString();
+
+        return ((GsmDataConnectionTracker)mDataConnection).getActiveApnString(apnType);
+    }
+
+    protected void log(String s) {
+        if (DBG)
+            Log.d(LOG_TAG, "[CDMALTEPhone] " + s);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 74adebd..dd5091c 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -66,6 +66,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.UUSInfo;
+import com.android.internal.telephony.CallTracker;
 
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
@@ -97,7 +98,6 @@
 
     // Instance Variables
     CdmaCallTracker mCT;
-    CdmaSMSDispatcher mSMS;
     CdmaServiceStateTracker mSST;
     RuimRecords mRuimRecords;
     RuimCard mRuimCard;
@@ -141,16 +141,25 @@
 
     // Constructors
     public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
-        this(context,ci,notifier, false);
+        super(notifier, context, ci, false);
+        initSST();
+        init(context, notifier);
     }
 
     public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
             boolean unitTestMode) {
         super(notifier, context, ci, unitTestMode);
+        initSST();
+        init(context, notifier);
+    }
 
+    protected void initSST() {
+        mSST = new CdmaServiceStateTracker(this);
+    }
+
+    protected void init(Context context, PhoneNotifier notifier) {
         mCM.setPhoneType(Phone.PHONE_TYPE_CDMA);
         mCT = new CdmaCallTracker(this);
-        mSST = new CdmaServiceStateTracker (this);
         mSMS = new CdmaSMSDispatcher(this);
         mIccFileHandler = new RuimFileHandler(this);
         mRuimRecords = new RuimRecords(this);
@@ -168,7 +177,7 @@
         mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mCM.registerForOn(this, EVENT_RADIO_ON, null);
         mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
-        mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
+        mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
         mCM.registerForNVReady(this, EVENT_NV_READY, null);
         mCM.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
 
@@ -220,7 +229,7 @@
             mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
             mCM.unregisterForOn(this); //EVENT_RADIO_ON
             mCM.unregisterForNVReady(this); //EVENT_NV_READY
-            mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
+            mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
             mCM.unSetOnSuppServiceNotification(this);
             removeCallbacks(mExitEcmRunnable);
 
@@ -270,10 +279,18 @@
         return mSST.ss;
     }
 
+    public CallTracker getCallTracker() {
+        return mCT;
+    }
+
     public Phone.State getState() {
         return mCT.state;
     }
 
+    public ServiceStateTracker getServiceStateTracker() {
+        return mSST;
+    }
+
     public String getPhoneName() {
         return "CDMA";
     }
@@ -625,7 +642,7 @@
                 case CONNECTED:
                 case DISCONNECTING:
                     if ( mCT.state != Phone.State.IDLE
-                            && !mSST.isConcurrentVoiceAndData()) {
+                            && !mSST.isConcurrentVoiceAndDataAllowed()) {
                         ret = DataState.SUSPENDED;
                     } else {
                         ret = DataState.CONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index a89f783..79f4152 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -134,6 +134,10 @@
     public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallStartedRegistrants.add(r);
+        // Notify if in call when registering
+        if (state != Phone.State.IDLE) {
+            r.notifyRegistrant(new AsyncResult(null, null, null));
+        }
     }
     public void unregisterForVoiceCallStarted(Handler h) {
         voiceCallStartedRegistrants.remove(h);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index fbe455e..1a15393 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -430,7 +430,7 @@
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
                         || serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
                     return DisconnectCause.OUT_OF_SERVICE;
-                } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
+                } else if (phone.mCM.getNvState() != CommandsInterface.RadioState.NV_READY
                         && phone.getIccCard().getState() != RuimCard.State.READY) {
                     return DisconnectCause.ICC_ERROR;
                 } else if (causeCode==CallFailCause.NORMAL_CLEARING) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 1a0dbc2..4f27e7f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -33,8 +33,8 @@
     private static final String LOG_TAG = "CDMA";
 
     // ***** Constructor
-    private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
-        super(phone, name, rm);
+    private CdmaDataConnection(CDMAPhone phone, String name, int id, RetryManager rm) {
+        super(phone, name, id, rm);
     }
 
     /**
@@ -49,11 +49,10 @@
         synchronized (mCountLock) {
             mCount += 1;
         }
-        CdmaDataConnection cdmaDc = new CdmaDataConnection(phone,
-                "CdmaDataConnection-" + mCount, rm);
+        CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDataConnection-" + mCount,
+                id, rm);
         cdmaDc.start();
         if (DBG) cdmaDc.log("Made " + cdmaDc.getName());
-        cdmaDc.mId = id;
         return cdmaDc;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 8c36106..345d0d9 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -104,8 +104,8 @@
         p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
         p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
         p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
-        p.mSST.registerForCdmaDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
-        p.mSST.registerForCdmaDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
+        p.mSST.registerForDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
+        p.mSST.registerForDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
         p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
         p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
         p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
@@ -128,8 +128,8 @@
         mPhone.mCM.unregisterForDataNetworkStateChanged(this);
         mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
         mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
-        mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this);
-        mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
+        mCdmaPhone.mSST.unregisterForDataConnectionAttached(this);
+        mCdmaPhone.mSST.unregisterForDataConnectionDetached(this);
         mCdmaPhone.mSST.unregisterForRoamingOn(this);
         mCdmaPhone.mSST.unregisterForRoamingOff(this);
         mPhone.mCM.unregisterForCdmaOtaProvision(this);
@@ -167,30 +167,6 @@
         return false;
     }
 
-    /**
-     * The data connection is expected to be setup while device
-     *  1. has ruim card or non-volatile data store
-     *  2. registered to data connection service
-     *  3. user doesn't explicitly disable data service
-     *  4. wifi is not on
-     *
-     * @return false while no data connection if all above requirements are met.
-     */
-    @Override
-    public boolean isDataConnectionAsDesired() {
-        boolean roaming = mPhone.getServiceState().getRoaming();
-
-        if (((mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
-                 mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
-                (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
-                 ServiceState.STATE_IN_SERVICE) &&
-                (!roaming || getDataOnRoamingEnabled()) &&
-                !mIsWifiConnected ) {
-            return (mState == State.CONNECTED);
-        }
-        return true;
-    }
-
     @Override
     protected boolean isDataAllowed() {
         int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
@@ -200,9 +176,9 @@
         boolean allowed =
                     (psState == ServiceState.STATE_IN_SERVICE ||
                             mAutoAttachOnCreation) &&
-                    (mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+                    (mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
                             mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
-                    (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+                    (mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
                             mPhone.getState() == Phone.State.IDLE) &&
                     !roaming &&
                     mInternalDataEnabled &&
@@ -214,11 +190,11 @@
             if (!((psState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
                 reason += " - psState= " + psState;
             }
-            if (!(mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
+            if (!(mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
                     mCdmaPhone.mRuimRecords.getRecordsLoaded())) {
-                reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded";
+                reason += " - radioState= " + mPhone.mCM.getNvState() + " - RUIM not loaded";
             }
-            if (!(mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+            if (!(mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
                     mPhone.getState() == Phone.State.IDLE)) {
                 reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
             }
@@ -262,9 +238,7 @@
     }
 
     /**
-     * Cleanup all connections.
-     *
-     * TODO: Cleanup only a specified connection passed as a parameter.
+     * Cleanup the CDMA data connection (only one is supported)
      *
      * @param tearDown true if the underlying DataConnection should be disconnected.
      * @param reason for the clean up.
@@ -354,7 +328,7 @@
         setState(State.CONNECTED);
         notifyDataConnection(reason);
         startNetStatPoll();
-        mRetryMgr.resetRetryCount();
+        mDataConnections.get(0).resetRetryCount();
     }
 
     private void resetPollStats() {
@@ -386,7 +360,7 @@
     protected void restartRadio() {
         if (DBG) log("Cleanup connection and wait " +
                 (TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio");
-        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+        cleanUpAllConnections();
         sendEmptyMessageDelayed(EVENT_RESTART_RADIO, TIME_DELAYED_TO_RESTART_RADIO);
         mPendingRestartRadio = true;
     }
@@ -504,7 +478,7 @@
              * at the last time until the state is changed.
              * TODO: Make this configurable?
              */
-            int nextReconnectDelay = mRetryMgr.getRetryTimer();
+            int nextReconnectDelay = mDataConnections.get(0).getRetryTimer();
             log("Data Connection activate failed. Scheduling next attempt for "
                     + (nextReconnectDelay / 1000) + "s");
 
@@ -518,7 +492,7 @@
                     SystemClock.elapsedRealtime() + nextReconnectDelay,
                     mReconnectIntent);
 
-            mRetryMgr.increaseRetryCount();
+            mDataConnections.get(0).increaseRetryCount();
 
             if (!shouldPostNotification(lastFailCauseCode)) {
                 log("NOT Posting Data Connection Unavailable notification "
@@ -543,14 +517,14 @@
 
     protected void onRecordsLoaded() {
         if (mState == State.FAILED) {
-            cleanUpConnection(false, null);
+            cleanUpAllConnections();
         }
         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
     }
 
     protected void onNVReady() {
         if (mState == State.FAILED) {
-            cleanUpConnection(false, null);
+            cleanUpAllConnections();
         }
         sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
     }
@@ -560,6 +534,7 @@
      */
     @Override
     protected void onEnableNewApn() {
+        // No mRequestedApnType check; only one connection is supported
         cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
     }
 
@@ -588,7 +563,7 @@
             trySetupData(Phone.REASON_ROAMING_ON);
         } else {
             if (DBG) log("Tear down data connection on roaming.");
-            cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+            cleanUpAllConnections();
         }
     }
 
@@ -609,7 +584,7 @@
         notifyDataAvailability(null);
 
         if (mState != State.IDLE) {
-            cleanUpConnection(true, null);
+            cleanUpAllConnections();
         }
     }
 
@@ -618,7 +593,7 @@
      */
     @Override
     protected void onRadioOffOrNotAvailable() {
-        mRetryMgr.resetRetryCount();
+        mDataConnections.get(0).resetRetryCount();
 
         if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
@@ -626,7 +601,7 @@
             log("We're on the simulator; assuming radio off is meaningless");
         } else {
             if (DBG) log("Radio is off and clean up all connection");
-            cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+            cleanUpAllConnections();
         }
     }
 
@@ -711,7 +686,7 @@
      */
     @Override
     protected void onVoiceCallStarted() {
-        if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+        if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
             stopNetStatPoll();
             notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
             notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED);
@@ -724,7 +699,7 @@
     @Override
     protected void onVoiceCallEnded() {
         if (mState == State.CONNECTED) {
-            if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+            if (!mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
                 startNetStatPoll();
                 notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
             } else {
@@ -733,34 +708,40 @@
             }
             notifyDataAvailability(Phone.REASON_VOICE_CALL_ENDED);
         } else {
-            mRetryMgr.resetRetryCount();
+            mDataConnections.get(0).resetRetryCount();
             // in case data setup was attempted when we were on a voice call
             trySetupData(Phone.REASON_VOICE_CALL_ENDED);
         }
     }
 
     @Override
-    protected void onCleanUpConnection(boolean tearDown, String reason) {
+    protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) {
+        // No apnId check; only one connection is supported
         cleanUpConnection(tearDown, reason);
     }
 
+    @Override
+    protected void onCleanUpAllConnections() {
+        // Only one CDMA connection is supported
+        cleanUpConnection(true, null);
+    }
+
     private void createAllDataConnectionList() {
         CdmaDataConnection dataConn;
 
-        /** TODO: Use one retry manager for all connections for now */
-        RetryManager rm = mRetryMgr;
-        if (!rm.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
-            if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
-                // Should never happen, log an error and default to a simple linear sequence.
-                log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
-                        + DEFAULT_DATA_RETRY_CONFIG);
-                rm.configure(20, 2000, 1000);
-            }
-        }
-
+        String retryConfig = SystemProperties.get("ro.cdma.data_retry_config");
         for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
-            int id = mUniqueIdGenerator.getAndIncrement();
+            RetryManager rm = new RetryManager();
+            if (!rm.configure(retryConfig)) {
+                if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+                    // Should never happen, log an error and default to a simple linear sequence.
+                    log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+                            + DEFAULT_DATA_RETRY_CONFIG);
+                    rm.configure(20, 2000, 1000);
+                }
+            }
 
+            int id = mUniqueIdGenerator.getAndIncrement();
             dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
             mDataConnections.put(id, dataConn);
         }
@@ -779,7 +760,7 @@
         } else {
             if (mState == State.FAILED) {
                 cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
-                mRetryMgr.resetRetryCount();
+                mDataConnections.get(0).resetRetryCount();
 
                 CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
                 EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
@@ -797,7 +778,7 @@
                 switch (otaPrivision[0]) {
                 case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
                 case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
-                    mRetryMgr.resetRetryCount();
+                    mDataConnections.get(0).resetRetryCount();
                     break;
                 default:
                     break;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
new file mode 100644
index 0000000..386b636
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.RILConstants;
+
+import android.telephony.SignalStrength;
+import android.telephony.ServiceState;
+import android.telephony.cdma.CdmaCellLocation;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.AsyncResult;
+import android.os.Message;
+
+import android.util.Log;
+import android.util.EventLog;
+
+import com.android.internal.telephony.RestrictedState;
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
+    static final String LOG_TAG = "CDMA";
+
+    CDMALTEPhone mCdmaLtePhone;
+
+    private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
+
+    private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
+
+    public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
+        super(phone);
+        mCdmaLtePhone = phone;
+        log("CdmaLteServiceStateTracker Constructors");
+    }
+
+    /**
+     * @return The current GPRS state. IN_SERVICE is the same as "attached" and
+     *         OUT_OF_SERVICE is the same as detached.
+     */
+    public int getCurrentDataConnectionState() {
+        return gprsState;
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+        int[] ints;
+        String[] strings;
+        if (msg.what == EVENT_POLL_STATE_GPRS) {
+            log("handleMessage EVENT_POLL_STATE_GPRS");
+            ar = (AsyncResult)msg.obj;
+            handlePollStateResult(msg.what, ar);
+        } else {
+            super.handleMessage(msg);
+        }
+    }
+
+    /**
+     * The LTE data connection state, only return true here
+     */
+    @Override
+    protected boolean checkAdditionalDataAvaiable() {
+        return newGPRSState != ServiceState.STATE_IN_SERVICE;
+    }
+
+    /**
+     * Handle the result of one of the pollState()-related requests
+     */
+    @Override
+    protected void handlePollStateResultMessage(int what, AsyncResult ar) {
+        if (what == EVENT_POLL_STATE_GPRS) {
+            log("handlePollStateResultMessage EVENT_POLL_STATE_GPRS");
+            String states[] = (String[])ar.result;
+
+            int type = 0;
+            int regState = -1;
+            if (states.length > 0) {
+                try {
+                    regState = Integer.parseInt(states[0]);
+
+                    // states[3] (if present) is the current radio technology
+                    if (states.length >= 4 && states[3] != null) {
+                        type = Integer.parseInt(states[3]);
+                    }
+                } catch (NumberFormatException ex) {
+                    Log.w(LOG_TAG,
+                            "[CdmaLteServiceStateTracker] error parsing GprsRegistrationState: "
+                                    + ex);
+                }
+            }
+
+            newGPRSState = regCodeToServiceState(regState);
+            // Not sure if this is needed in CDMALTE phone.
+            // mDataRoaming = regCodeIsRoaming(regState);
+            if (newGPRSState == ServiceState.STATE_IN_SERVICE) {
+                this.newCdmaDataConnectionState = newGPRSState;
+                newNetworkType = type;
+                newSS.setRadioTechnology(type);
+            }
+        } else {
+            super.handlePollStateResultMessage(what, ar);
+        }
+    }
+
+    @Override
+    protected void setSignalStrengthDefaultValues() {
+        mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, false);
+    }
+
+    @Override
+    protected void pollState() {
+        pollingContext = new int[1];
+        pollingContext[0] = 0;
+
+        switch (cm.getRadioState()) {
+            case RADIO_UNAVAILABLE:
+                newSS.setStateOutOfService();
+                newCellLoc.setStateInvalid();
+                setSignalStrengthDefaultValues();
+                mGotCountryCode = false;
+
+                pollStateDone();
+                break;
+
+            case RADIO_OFF:
+                newSS.setStateOff();
+                newCellLoc.setStateInvalid();
+                setSignalStrengthDefaultValues();
+                mGotCountryCode = false;
+
+                pollStateDone();
+                break;
+
+            case SIM_NOT_READY:
+            case SIM_LOCKED_OR_ABSENT:
+            case SIM_READY:
+                log("Radio Technology Change ongoing, setting SS to off");
+                newSS.setStateOff();
+                newCellLoc.setStateInvalid();
+                setSignalStrengthDefaultValues();
+                mGotCountryCode = false;
+                // NOTE: pollStateDone() is not needed in this case
+                break;
+
+            default:
+                // Issue all poll-related commands at once, then count
+                // down the responses which are allowed to arrive
+                // out-of-order.
+
+                pollingContext[0]++;
+                // RIL_REQUEST_OPERATOR is necessary for CDMA
+                cm.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
+
+                pollingContext[0]++;
+                // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA
+                cm.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA,
+                        pollingContext));
+
+                int networkMode = android.provider.Settings.Secure.getInt(phone.getContext()
+                        .getContentResolver(),
+                        android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+                        RILConstants.PREFERRED_NETWORK_MODE);
+                Log.v(LOG_TAG, "[CdmaLteServiceStateTracker] The network mode here is = "
+                        + networkMode);
+                if ((networkMode == RILConstants.NETWORK_MODE_GLOBAL)
+                        || (networkMode == RILConstants.NETWORK_MODE_LTE_ONLY)) {
+                    pollingContext[0]++;
+                    // RIL_REQUEST_DATA_REGISTRATION_STATE
+                    cm.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS,
+                                                pollingContext));
+                }
+                break;
+        }
+    }
+
+    protected static String networkTypeToString(int type) {
+        String ret = "unknown";
+
+        switch (type) {
+            case DATA_ACCESS_CDMA_IS95A:
+            case DATA_ACCESS_CDMA_IS95B:
+                ret = "CDMA";
+                break;
+            case DATA_ACCESS_CDMA_1xRTT:
+                ret = "CDMA - 1xRTT";
+                break;
+            case DATA_ACCESS_CDMA_EvDo_0:
+                ret = "CDMA - EvDo rev. 0";
+                break;
+            case DATA_ACCESS_CDMA_EvDo_A:
+                ret = "CDMA - EvDo rev. A";
+                break;
+            case DATA_ACCESS_CDMA_EvDo_B:
+                ret = "CDMA - EvDo rev. B";
+                break;
+            case DATA_ACCESS_LTE:
+                ret = "LTE";
+                break;
+            case DATA_ACCESS_EHRPD:
+                ret = "CDMA - eHRPD";
+            default:
+                if (DBG) {
+                    Log.e(LOG_TAG, " [CdmaLteServiceStateTracker] Wrong network."
+                           + " Can not return a string.");
+                }
+                break;
+        }
+        return ret;
+    }
+
+    @Override
+    protected void pollStateDone() {
+        log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]");
+
+        boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
+                && newSS.getState() == ServiceState.STATE_IN_SERVICE;
+
+        boolean hasDeregistered = ss.getState() == ServiceState.STATE_IN_SERVICE
+                && newSS.getState() != ServiceState.STATE_IN_SERVICE;
+
+        boolean hasCdmaDataConnectionAttached =
+            this.cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE
+                && this.newCdmaDataConnectionState == ServiceState.STATE_IN_SERVICE;
+
+        boolean hasCdmaDataConnectionDetached =
+            this.cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE
+                && this.newCdmaDataConnectionState != ServiceState.STATE_IN_SERVICE;
+
+        boolean hasCdmaDataConnectionChanged =
+            cdmaDataConnectionState != newCdmaDataConnectionState;
+
+        boolean hasNetworkTypeChanged = networkType != newNetworkType;
+
+        boolean hasChanged = !newSS.equals(ss);
+
+        boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
+
+        boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
+
+        boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
+
+        boolean has4gHandoff =
+            ((networkType == DATA_ACCESS_LTE) && (newNetworkType == DATA_ACCESS_EHRPD))
+                || ((networkType == DATA_ACCESS_EHRPD) && (newNetworkType == DATA_ACCESS_LTE));
+
+        boolean hasMultiApnSupport =
+            (((newNetworkType == DATA_ACCESS_LTE) || (newNetworkType == DATA_ACCESS_EHRPD)) 
+                    && ((networkType != DATA_ACCESS_LTE) && (networkType != DATA_ACCESS_EHRPD)));
+
+        boolean hasLostMultiApnSupport =
+            ((newNetworkType >= DATA_ACCESS_CDMA_IS95A)
+                    && (newNetworkType <= DATA_ACCESS_CDMA_EvDo_A));
+
+        log("hasRegistered = " + hasRegistered + " hasCdmaDataConnectionAttached = "
+                + hasCdmaDataConnectionAttached + " hasCdmaDataConnectionChanged = "
+                + hasCdmaDataConnectionChanged + " hasNetworkTypeChanged = "
+                + hasNetworkTypeChanged + " has4gHandoff = " + has4gHandoff
+                + " hasMultiApnSupport = " + hasMultiApnSupport + " hasLostMultiApnSupport = "
+                + hasLostMultiApnSupport);
+        // Add an event log when connection state changes
+        if (ss.getState() != newSS.getState()
+                || cdmaDataConnectionState != newCdmaDataConnectionState) {
+            EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, ss.getState(),
+                    cdmaDataConnectionState, newSS.getState(), newCdmaDataConnectionState);
+        }
+
+        ServiceState tss;
+        tss = ss;
+        ss = newSS;
+        newSS = tss;
+        // clean slate for next time
+        newSS.setStateOutOfService();
+
+        // TODO: 4G Tech Handoff
+        // if (has4gHandoff) {
+        // Message msg = phone.mDataConnection.obtainMessage(
+        // DataConnectionTracker.EVENT_4G_TECHNOLOGY_CHANGE);
+        // phone.mDataConnection.sendMessage(msg);
+        // }
+
+        if ((hasMultiApnSupport)
+                && (phone.mDataConnection instanceof CdmaDataConnectionTracker)) {
+            log("GsmDataConnectionTracker Created");
+            phone.mDataConnection.dispose();
+            phone.mDataConnection = new GsmDataConnectionTracker(mCdmaLtePhone);
+        }
+
+        if ((hasLostMultiApnSupport)
+                && (phone.mDataConnection instanceof GsmDataConnectionTracker)) {
+            log("GsmDataConnectionTracker disposed");
+            phone.mDataConnection.dispose();
+            phone.mDataConnection = new CdmaDataConnectionTracker((CDMAPhone)phone);
+        }
+
+        CdmaCellLocation tcl = cellLoc;
+        cellLoc = newCellLoc;
+        newCellLoc = tcl;
+
+        cdmaDataConnectionState = newCdmaDataConnectionState;
+        networkType = newNetworkType;
+
+        gprsState = newCdmaDataConnectionState;
+
+        newSS.setStateOutOfService(); // clean slate for next time
+
+        if (hasNetworkTypeChanged) {
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
+                    networkTypeToString(networkType));
+        }
+
+        if (hasRegistered) {
+            mNetworkAttachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasChanged) {
+            if (cm.getNvState().isNVReady()) {
+                String eriText;
+                // Now the CDMAPhone sees the new ServiceState so it can get the
+                // new ERI text
+                if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+                    eriText = phone.getCdmaEriText();
+                } else {
+                    // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
+                    // for
+                    // mRegistrationState 0,2,3 and 4
+                    eriText = phone.getContext()
+                            .getText(com.android.internal.R.string.roamingTextSearching).toString();
+                }
+                ss.setCdmaEriText(eriText);
+            }
+
+            String operatorNumeric;
+
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
+                    ss.getOperatorAlphaLong());
+
+            operatorNumeric = ss.getOperatorNumeric();
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+
+            if (operatorNumeric == null) {
+                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
+            } else {
+                String isoCountryCode = "";
+                try {
+                    isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric
+                            .substring(0, 3)));
+                } catch (NumberFormatException ex) {
+                    Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+                } catch (StringIndexOutOfBoundsException ex) {
+                    Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+                }
+
+                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
+                        isoCountryCode);
+                mGotCountryCode = true;
+                if (mNeedFixZone) {
+                    fixTimeZone(isoCountryCode);
+                }
+            }
+
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
+                    ss.getRoaming() ? "true" : "false");
+
+            updateSpnDisplay();
+            phone.notifyServiceStateChanged(ss);
+        }
+
+        if (hasCdmaDataConnectionAttached) {
+            mAttachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasCdmaDataConnectionDetached) {
+            mDetachedRegistrants.notifyRegistrants();
+        }
+
+        if ((hasCdmaDataConnectionChanged || hasNetworkTypeChanged)
+                && (phone.mDataConnection instanceof CdmaDataConnectionTracker)) {
+            phone.notifyDataConnection();
+        }
+
+        if (hasRoamingOn) {
+            mRoamingOnRegistrants.notifyRegistrants();
+        }
+
+        if (hasRoamingOff) {
+            mRoamingOffRegistrants.notifyRegistrants();
+        }
+
+        if (hasLocationChanged) {
+            phone.notifyLocationChanged();
+        }
+    }
+
+    protected void onSignalStrengthResult(AsyncResult ar) {
+        SignalStrength oldSignalStrength = mSignalStrength;
+
+        if (ar.exception != null) {
+            // Most likely radio is resetting/disconnected change to default
+            // values.
+            setSignalStrengthDefaultValues();
+        } else {
+            int[] ints = (int[])ar.result;
+            int lteCqi = 99, lteRsrp = -1;
+            int lteRssi = 99;
+            int offset = 2;
+            int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -120;
+            int cdmaEcio = (ints[offset + 1] > 0) ? -ints[offset + 1] : -160;
+            int evdoRssi = (ints[offset + 2] > 0) ? -ints[offset + 2] : -120;
+            int evdoEcio = (ints[offset + 3] > 0) ? -ints[offset + 3] : -1;
+            int evdoSnr = ((ints[offset + 4] > 0) && (ints[offset + 4] <= 8)) ? ints[offset + 4]
+                    : -1;
+            if (networkType == ServiceState.RADIO_TECHNOLOGY_LTE) {
+                lteRssi = (ints[offset + 5] >= 0) ? ints[offset + 5] : 99;
+                lteRsrp = (ints[offset + 6] > 0) ? -ints[offset + 7] : -1;
+                lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 6] : 99;
+            }
+
+            if (networkType != ServiceState.RADIO_TECHNOLOGY_LTE) {
+                mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio, evdoRssi, evdoEcio,
+                        evdoSnr, false);
+            } else {
+                mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio, evdoRssi, evdoEcio,
+                        evdoSnr, lteRssi, lteRsrp, -1, -1, lteCqi, true);
+            }
+        }
+
+        try {
+            phone.notifySignalStrength();
+        } catch (NullPointerException ex) {
+            log("onSignalStrengthResult() Phone already destroyed: " + ex
+                    + "SignalStrength not notified");
+        }
+    }
+
+    public boolean isConcurrentVoiceAndDataAllowed() {
+        // Note: it needs to be confirmed which CDMA network types
+        // can support voice and data calls concurrently.
+        // For the time-being, the return value will be false.
+        // return (networkType >= DATA_ACCESS_LTE);
+        return false;
+    }
+
+    @Override
+    protected void log(String s) {
+        if (DBG)
+            Log.d(LOG_TAG, "[CdmaLteServiceStateTracker] " + s);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 6bd2d09..c0bfd23 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -94,7 +94,7 @@
 
     /** {@inheritDoc} */
     @Override
-    protected int dispatchMessage(SmsMessageBase smsb) {
+    public int dispatchMessage(SmsMessageBase smsb) {
 
         // If sms is null, means there was a parsing error.
         if (smsb == null) {
@@ -485,19 +485,19 @@
 
     /** {@inheritDoc} */
     @Override
-    protected void activateCellBroadcastSms(int activate, Message response) {
+    public void activateCellBroadcastSms(int activate, Message response) {
         mCm.setCdmaBroadcastActivation((activate == 0), response);
     }
 
     /** {@inheritDoc} */
     @Override
-    protected void getCellBroadcastSmsConfig(Message response) {
+    public void getCellBroadcastSmsConfig(Message response) {
         mCm.getCdmaBroadcastConfig(response);
     }
 
     /** {@inheritDoc} */
     @Override
-    protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+    public void setCellBroadcastConfig(int[] configValuesArray, Message response) {
         mCm.setCdmaBroadcastConfig(configValuesArray, response);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 0debb42..6966345 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.telephony.cdma;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
-
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DataConnectionTracker;
@@ -61,7 +59,7 @@
 /**
  * {@hide}
  */
-final class CdmaServiceStateTracker extends ServiceStateTracker {
+public class CdmaServiceStateTracker extends ServiceStateTracker {
     static final String LOG_TAG = "CDMA";
 
     CDMAPhone phone;
@@ -88,8 +86,8 @@
     /**
      *  Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
      */
-    private int networkType = 0;
-    private int newNetworkType = 0;
+    protected int networkType = 0;
+    protected int newNetworkType = 0;
 
     private boolean mCdmaRoaming = false;
     private int mRoamingIndicator;
@@ -99,23 +97,21 @@
     /**
      * Initially assume no data connection.
      */
-    private int cdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
-    private int newCdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
-    private int mRegistrationState = -1;
-    private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
-    private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
-    private RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
+    protected int cdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+    protected int newCdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+    protected int mRegistrationState = -1;
+    protected RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
 
     /**
      * Sometimes we get the NITZ time before we know what country we
      * are in. Keep the time zone information from the NITZ string so
      * we can fix the time zone once know the country.
      */
-    private boolean mNeedFixZone = false;
+    protected boolean mNeedFixZone = false;
     private int mZoneOffset;
     private boolean mZoneDst;
     private long mZoneTime;
-    private boolean mGotCountryCode = false;
+    protected boolean mGotCountryCode = false;
     String mSavedTimeZone;
     long mSavedTime;
     long mSavedAtTime;
@@ -232,57 +228,6 @@
         if (DBG) log("CdmaServiceStateTracker finalized");
     }
 
-    void registerForNetworkAttach(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        networkAttachedRegistrants.add(r);
-
-        if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForNetworkAttach(Handler h) {
-        networkAttachedRegistrants.remove(h);
-    }
-
-    /**
-     * Registration point for transition into Data attached.
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        cdmaDataConnectionAttachedRegistrants.add(r);
-
-        if (cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForCdmaDataConnectionAttached(Handler h) {
-        cdmaDataConnectionAttachedRegistrants.remove(h);
-    }
-
-    /**
-     * Registration point for transition into Data detached.
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        cdmaDataConnectionDetachedRegistrants.add(r);
-
-        if (cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForCdmaDataConnectionDetached(Handler h) {
-        cdmaDataConnectionDetachedRegistrants.remove(h);
-    }
-
     /**
      * Registration point for subscription info ready
      * @param h handler to notify
@@ -566,37 +511,21 @@
             cm.setRadioPower(true, null);
         } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
             DataConnectionTracker dcTracker = phone.mDataConnection;
-            if (! dcTracker.isDataConnectionAsDesired()) {
-                EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
-                        dcTracker.getStateInString(),
-                        dcTracker.getAnyDataEnabled() ? 1 : 0);
-            }
 
             // If it's on and available and we want it off gracefully
             powerOffRadioSafely();
         } // Otherwise, we're in the desired state
     }
 
+    // TODO: Consider moving this method to DataConnectionTracker
     @Override
-    protected void powerOffRadioSafely() {
+    public void powerOffRadioSafely() {
         DataConnectionTracker dcTracker = phone.mDataConnection;
 
-        Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
-        msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
-
         synchronized (this) {
             if (!mPendingRadioPowerOffAfterDataOff) {
-                DataConnectionTracker.State currentState = dcTracker.getState();
-                if (currentState != DataConnectionTracker.State.CONNECTED
-                    && currentState != DataConnectionTracker.State.DISCONNECTING
-                    && currentState != DataConnectionTracker.State.INITING) {
-                    msg.arg1 = 0; // tearDown is false as it is not needed.
-                    dcTracker.sendMessage(msg);
-                    if (DBG) log("Data disconnected, turn off radio right away.");
-                    hangupAndPowerOff();
-                } else {
-                    msg.arg1 = 1; // tearDown is true
-                    dcTracker.sendMessage(msg);
+                if (dcTracker.isAnyActiveDataConnections()) {
+                    dcTracker.cleanUpAllConnections();
                     if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) {
                         if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
                         mPendingRadioPowerOffAfterDataOff = true;
@@ -604,6 +533,10 @@
                         Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away.");
                         hangupAndPowerOff();
                     }
+                } else {
+                    dcTracker.cleanUpAllConnections();
+                    if (DBG) log("Data disconnected, turn off radio right away.");
+                    hangupAndPowerOff();
                 }
             }
         }
@@ -647,14 +580,167 @@
     }
 
     /**
-     * Handle the result of one of the pollState()-related requests
-     */
+    * The LTE data connection state, only return true here
+    */
+    protected boolean checkAdditionalDataAvaiable(){
+        return true;
+    }
 
-    @Override
-    protected void handlePollStateResult (int what, AsyncResult ar) {
+    /**
+    * Hanlde the PollStateResult message
+    */
+    protected void handlePollStateResultMessage(int what, AsyncResult ar){
         int ints[];
         String states[];
+        switch (what) {
+        case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
+            states = (String[])ar.result;
 
+            int registrationState = 4;     //[0] registrationState
+            int radioTechnology = -1;      //[3] radioTechnology
+            int baseStationId = -1;        //[4] baseStationId
+            //[5] baseStationLatitude
+            int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+            //[6] baseStationLongitude
+            int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+            int cssIndicator = 0;          //[7] init with 0, because it is treated as a boolean
+            int systemId = 0;              //[8] systemId
+            int networkId = 0;             //[9] networkId
+            int roamingIndicator = -1;     //[10] Roaming indicator
+            int systemIsInPrl = 0;         //[11] Indicates if current system is in PRL
+            int defaultRoamingIndicator = 0;  //[12] Is default roaming indicator from PRL
+            int reasonForDenial = 0;       //[13] Denial reason if registrationState = 3
+
+            if (states.length == 14) {
+                try {
+                    if (states[0] != null) {
+                        registrationState = Integer.parseInt(states[0]);
+                    }
+                    if (states[3] != null) {
+                        radioTechnology = Integer.parseInt(states[3]);
+                    }
+                    if (states[4] != null) {
+                        baseStationId = Integer.parseInt(states[4]);
+                    }
+                    if (states[5] != null) {
+                        baseStationLatitude = Integer.parseInt(states[5]);
+                    }
+                    if (states[6] != null) {
+                        baseStationLongitude = Integer.parseInt(states[6]);
+                    }
+                    // Some carriers only return lat-lngs of 0,0
+                    if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+                        baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
+                        baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+                    }
+                    if (states[7] != null) {
+                        cssIndicator = Integer.parseInt(states[7]);
+                    }
+                    if (states[8] != null) {
+                        systemId = Integer.parseInt(states[8]);
+                    }
+                    if (states[9] != null) {
+                        networkId = Integer.parseInt(states[9]);
+                    }
+                    if (states[10] != null) {
+                        roamingIndicator = Integer.parseInt(states[10]);
+                    }
+                    if (states[11] != null) {
+                        systemIsInPrl = Integer.parseInt(states[11]);
+                    }
+                    if (states[12] != null) {
+                        defaultRoamingIndicator = Integer.parseInt(states[12]);
+                    }
+                    if (states[13] != null) {
+                        reasonForDenial = Integer.parseInt(states[13]);
+                    }
+                } catch (NumberFormatException ex) {
+                    Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
+                }
+            } else {
+                throw new RuntimeException("Warning! Wrong number of parameters returned from "
+                                     + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
+                                     + states.length);
+            }
+
+            mRegistrationState = registrationState;
+            // When registration state is roaming and TSB58
+            // roaming indicator is not in the carrier-specified
+            // list of ERIs for home system, mCdmaRoaming is true.
+            mCdmaRoaming =
+                    regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
+            newSS.setState (regCodeToServiceState(registrationState));
+
+            if(checkAdditionalDataAvaiable()) {
+                this.newCdmaDataConnectionState =
+                        radioTechnologyToDataServiceState(radioTechnology);
+                newSS.setRadioTechnology(radioTechnology);
+                newNetworkType = radioTechnology;
+            }
+
+            newSS.setCssIndicator(cssIndicator);
+            newSS.setSystemAndNetworkId(systemId, networkId);
+            mRoamingIndicator = roamingIndicator;
+            mIsInPrl = (systemIsInPrl == 0) ? false : true;
+            mDefaultRoamingIndicator = defaultRoamingIndicator;
+
+
+            // Values are -1 if not available.
+            newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
+                    baseStationLongitude, systemId, networkId);
+
+            if (reasonForDenial == 0) {
+                mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
+            } else if (reasonForDenial == 1) {
+                mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
+            } else {
+                mRegistrationDeniedReason = "";
+            }
+
+            if (mRegistrationState == 3) {
+                if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
+            }
+            break;
+
+        case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
+            String opNames[] = (String[])ar.result;
+
+            if (opNames != null && opNames.length >= 3) {
+                // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
+                if ((opNames[2] == null) || (opNames[2].length() < 5)
+                        || ("00000".equals(opNames[2]))) {
+                    opNames[2] = SystemProperties.get(
+                            CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
+                    if (DBG) {
+                        log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
+                                " is bad. Using SystemProperties '" +
+                                        CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
+                                "'= " + opNames[2]);
+                    }
+                }
+                if (cm.getNvState().isNVReady()) {
+                    // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
+                    // ERI text, so here it is ignored what is coming from the modem.
+                    newSS.setOperatorName(null, opNames[1], opNames[2]);
+                } else {
+                    newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+                }
+            } else {
+                Log.w(LOG_TAG, "error parsing opNames");
+            }
+            break;
+        default:
+            Log.e(LOG_TAG, "RIL response handle in wrong phone!"
+                + " Expected CDMA RIL request and get GSM RIL request.");
+        break;
+        }
+    }
+
+    /**
+     * Handle the result of one of the pollState() - related requests
+     */
+    @Override
+    protected void handlePollStateResult (int what, AsyncResult ar) {
         // Ignore stale requests from last poll.
         if (ar.userObj != pollingContext) return;
 
@@ -684,148 +770,7 @@
                         ar.exception);
             }
         } else try {
-            switch (what) {
-            case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
-                states = (String[])ar.result;
-
-                int registrationState = 4;     //[0] registrationState
-                int radioTechnology = -1;      //[3] radioTechnology
-                int baseStationId = -1;        //[4] baseStationId
-                //[5] baseStationLatitude
-                int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
-                //[6] baseStationLongitude
-                int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
-                int cssIndicator = 0;          //[7] init with 0, because it is treated as a boolean
-                int systemId = 0;              //[8] systemId
-                int networkId = 0;             //[9] networkId
-                int roamingIndicator = -1;     //[10] Roaming indicator
-                int systemIsInPrl = 0;         //[11] Indicates if current system is in PRL
-                int defaultRoamingIndicator = 0;  //[12] Is default roaming indicator from PRL
-                int reasonForDenial = 0;       //[13] Denial reason if registrationState = 3
-
-                if (states.length == 14) {
-                    try {
-                        if (states[0] != null) {
-                            registrationState = Integer.parseInt(states[0]);
-                        }
-                        if (states[3] != null) {
-                            radioTechnology = Integer.parseInt(states[3]);
-                        }
-                        if (states[4] != null) {
-                            baseStationId = Integer.parseInt(states[4]);
-                        }
-                        if (states[5] != null) {
-                            baseStationLatitude = Integer.parseInt(states[5]);
-                        }
-                        if (states[6] != null) {
-                            baseStationLongitude = Integer.parseInt(states[6]);
-                        }
-                        // Some carriers only return lat-lngs of 0,0
-                        if (baseStationLatitude == 0 && baseStationLongitude == 0) {
-                            baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
-                            baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
-                        }
-                        if (states[7] != null) {
-                            cssIndicator = Integer.parseInt(states[7]);
-                        }
-                        if (states[8] != null) {
-                            systemId = Integer.parseInt(states[8]);
-                        }
-                        if (states[9] != null) {
-                            networkId = Integer.parseInt(states[9]);
-                        }
-                        if (states[10] != null) {
-                            roamingIndicator = Integer.parseInt(states[10]);
-                        }
-                        if (states[11] != null) {
-                            systemIsInPrl = Integer.parseInt(states[11]);
-                        }
-                        if (states[12] != null) {
-                            defaultRoamingIndicator = Integer.parseInt(states[12]);
-                        }
-                        if (states[13] != null) {
-                            reasonForDenial = Integer.parseInt(states[13]);
-                        }
-                    } catch (NumberFormatException ex) {
-                        Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
-                    }
-                } else {
-                    throw new RuntimeException("Warning! Wrong number of parameters returned from "
-                                         + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
-                                         + states.length);
-                }
-
-                mRegistrationState = registrationState;
-                // When registration state is roaming and TSB58
-                // roaming indicator is not in the carrier-specified
-                // list of ERIs for home system, mCdmaRoaming is true.
-                mCdmaRoaming =
-                        regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
-                newSS.setState (regCodeToServiceState(registrationState));
-
-                this.newCdmaDataConnectionState =
-                        radioTechnologyToDataServiceState(radioTechnology);
-                newSS.setRadioTechnology(radioTechnology);
-                newNetworkType = radioTechnology;
-
-                newSS.setCssIndicator(cssIndicator);
-                newSS.setSystemAndNetworkId(systemId, networkId);
-                mRoamingIndicator = roamingIndicator;
-                mIsInPrl = (systemIsInPrl == 0) ? false : true;
-                mDefaultRoamingIndicator = defaultRoamingIndicator;
-
-
-                // Values are -1 if not available.
-                newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
-                        baseStationLongitude, systemId, networkId);
-
-                if (reasonForDenial == 0) {
-                    mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
-                } else if (reasonForDenial == 1) {
-                    mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
-                } else {
-                    mRegistrationDeniedReason = "";
-                }
-
-                if (mRegistrationState == 3) {
-                    if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
-                }
-                break;
-
-            case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
-                String opNames[] = (String[])ar.result;
-
-                if (opNames != null && opNames.length >= 3) {
-                    // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
-                    if ((opNames[2] == null) || (opNames[2].length() < 5)
-                            || ("00000".equals(opNames[2]))) {
-                        opNames[2] = SystemProperties.get(
-                                CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
-                        if (DBG) {
-                            log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
-                                    " is bad. Using SystemProperties '" +
-                                            CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
-                                    "'= " + opNames[2]);
-                        }
-                    }
-                    if (cm.getRadioState().isNVReady()) {
-                        // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
-                        // ERI text, so here it is ignored what is coming from the modem.
-                        newSS.setOperatorName(null, opNames[1], opNames[2]);
-                    } else {
-                        newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
-                    }
-                } else {
-                    Log.w(LOG_TAG, "error parsing opNames");
-                }
-                break;
-
-            default:
-                Log.e(LOG_TAG, "RIL response handle in wrong phone!"
-                    + " Expected CDMA RIL request and get GSM RIL request.");
-            break;
-            }
-
+            handlePollStateResultMessage(what, ar);
         } catch (RuntimeException ex) {
             Log.e(LOG_TAG, "Exception while polling service state. "
                     + "Probably malformed RIL response.", ex);
@@ -896,9 +841,8 @@
 
     }
 
-    private void setSignalStrengthDefaultValues() {
-        mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1,
-                -1, -1, -1, -1, -1, false);
+    protected void setSignalStrengthDefaultValues() {
+        mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, false);
     }
 
     /**
@@ -909,7 +853,7 @@
      * and start over again if the radio notifies us that some
      * event has changed
      */
-    private void
+    protected void
     pollState() {
         pollingContext = new int[1];
         pollingContext[0] = 0;
@@ -964,7 +908,7 @@
         }
     }
 
-    private static String networkTypeToString(int type) {
+    protected static String networkTypeToString(int type) {
         String ret = "unknown";
 
         switch (type) {
@@ -994,7 +938,7 @@
         return ret;
     }
 
-    private void fixTimeZone(String isoCountryCode) {
+    protected void fixTimeZone(String isoCountryCode) {
         TimeZone zone = null;
         // If the offset is (0, false) and the time zone property
         // is set, use the time zone property rather than GMT.
@@ -1031,7 +975,7 @@
         }
     }
 
-    private void pollStateDone() {
+    protected void pollStateDone() {
         if (DBG) log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]");
 
         boolean hasRegistered =
@@ -1095,7 +1039,7 @@
         }
 
         if (hasRegistered) {
-            networkAttachedRegistrants.notifyRegistrants();
+            mNetworkAttachedRegistrants.notifyRegistrants();
         }
 
         if (hasChanged) {
@@ -1150,11 +1094,11 @@
         }
 
         if (hasCdmaDataConnectionAttached) {
-            cdmaDataConnectionAttachedRegistrants.notifyRegistrants();
+            mAttachedRegistrants.notifyRegistrants();
         }
 
         if (hasCdmaDataConnectionDetached) {
-            cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
+            mDetachedRegistrants.notifyRegistrants();
         }
 
         if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
@@ -1162,11 +1106,11 @@
         }
 
         if (hasRoamingOn) {
-            roamingOnRegistrants.notifyRegistrants();
+            mRoamingOnRegistrants.notifyRegistrants();
         }
 
         if (hasRoamingOff) {
-            roamingOffRegistrants.notifyRegistrants();
+            mRoamingOffRegistrants.notifyRegistrants();
         }
 
         if (hasLocationChanged) {
@@ -1234,7 +1178,7 @@
      *  send signal-strength-changed notification if changed
      *  Called both for solicited and unsolicited signal strength updates
      */
-    private void
+    protected void
     onSignalStrengthResult(AsyncResult ar) {
         SignalStrength oldSignalStrength = mSignalStrength;
 
@@ -1253,7 +1197,7 @@
             //log(String.format("onSignalStrengthResult cdmaDbm=%d cdmaEcio=%d evdoRssi=%d evdoEcio=%d evdoSnr=%d",
             //        cdmaDbm, cdmaEcio, evdoRssi, evdoEcio, evdoSnr));
             mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio,
-                    evdoRssi, evdoEcio, evdoSnr, -1, -1, -1, -1, -1, false);
+                    evdoRssi, evdoEcio, evdoSnr, false);
         }
 
         try {
@@ -1289,7 +1233,7 @@
     }
 
     /** code is registration state 0-5 from TS 27.007 7.2 */
-    private int
+    protected int
     regCodeToServiceState(int code) {
         switch (code) {
         case 0: // Not searching and not registered
@@ -1319,6 +1263,13 @@
     }
 
     /**
+    * TODO: In the future, we need remove getCurrentCdmaDataConnectionState
+    */
+    public int getCurrentDataConnectionState() {
+        return cdmaDataConnectionState;
+    }
+
+    /**
      * code is registration state 0-5 from TS 27.007 7.2
      * returns true if registered roam, false otherwise
      */
@@ -1662,7 +1613,7 @@
      * @return true if phone is camping on a technology
      * that could support voice and data simultaneously.
      */
-    boolean isConcurrentVoiceAndData() {
+    public boolean isConcurrentVoiceAndDataAllowed() {
         // Note: it needs to be confirmed which CDMA network types
         // can support voice and data calls concurrently.
         // For the time-being, the return value will be false.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index c17197e..261a61a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -33,6 +33,7 @@
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import com.android.internal.telephony.CallTracker;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -72,6 +73,7 @@
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 import com.android.internal.telephony.IccVmNotSupportedException;
+import com.android.internal.telephony.ServiceStateTracker;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -100,9 +102,6 @@
     // Instance Variables
     GsmCallTracker mCT;
     GsmServiceStateTracker mSST;
-    GsmSMSDispatcher mSMS;
-    SIMRecords mSIMRecords;
-    SimCard mSimCard;
     CatService mStkService;
     ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
     SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
@@ -160,7 +159,7 @@
         mCM.registerForOn(this, EVENT_RADIO_ON, null);
         mCM.setOnUSSD(this, EVENT_USSD, null);
         mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
-        mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
+        mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
 
         if (false) {
             try {
@@ -210,7 +209,7 @@
             mSIMRecords.unregisterForRecordsLoaded(this); //EVENT_SIM_RECORDS_LOADED
             mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
             mCM.unregisterForOn(this); //EVENT_RADIO_ON
-            mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
+            mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
             mCM.unSetOnUSSD(this);
             mCM.unSetOnSuppServiceNotification(this);
 
@@ -283,6 +282,14 @@
         return mSIMRecords.getVoiceCallForwardingFlag();
     }
 
+    public CallTracker getCallTracker() {
+        return mCT;
+    }
+
+    public ServiceStateTracker getServiceStateTracker() {
+        return mSST;
+    }
+
     public List<? extends MmiCode>
     getPendingMmiCodes() {
         return mPendingMMIs;
@@ -314,7 +321,7 @@
                 case CONNECTED:
                 case DISCONNECTING:
                     if ( mCT.state != Phone.State.IDLE
-                            && !mSST.isConcurrentVoiceAndData()) {
+                            && !mSST.isConcurrentVoiceAndDataAllowed()) {
                         ret = DataState.SUSPENDED;
                     } else {
                         ret = DataState.CONNECTED;
@@ -404,7 +411,7 @@
         mNotifier.notifySignalStrength(this);
     }
 
-    /*package*/ void
+    public void
     notifyDataConnectionFailed(String reason, String apnType) {
         mNotifier.notifyDataConnectionFailed(this, reason, apnType);
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index 7dc2504..0870d5b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -374,11 +374,11 @@
                 } else if (phone.getIccCard().getState() != SimCard.State.READY) {
                     return DisconnectCause.ICC_ERROR;
                 } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
-                    if (phone.mSST.rs.isCsRestricted()) {
+                    if (phone.mSST.mRestrictedState.isCsRestricted()) {
                         return DisconnectCause.CS_RESTRICTED;
-                    } else if (phone.mSST.rs.isCsEmergencyRestricted()) {
+                    } else if (phone.mSST.mRestrictedState.isCsEmergencyRestricted()) {
                         return DisconnectCause.CS_RESTRICTED_EMERGENCY;
-                    } else if (phone.mSST.rs.isCsNormalRestricted()) {
+                    } else if (phone.mSST.mRestrictedState.isCsNormalRestricted()) {
                         return DisconnectCause.CS_RESTRICTED_NORMAL;
                     } else {
                         return DisconnectCause.ERROR_UNSPECIFIED;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 4689b2d..344486a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -19,10 +19,12 @@
 import android.os.Message;
 import android.util.Log;
 import android.util.Patterns;
+import android.text.TextUtils;
 
 import com.android.internal.telephony.ApnSetting;
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.RetryManager;
 
@@ -36,9 +38,11 @@
     //***** Instance Variables
     private ApnSetting apn;
 
+    protected int mProfileId = RILConstants.DATA_PROFILE_DEFAULT;
+    protected String mActiveApnType = Phone.APN_TYPE_DEFAULT;
     //***** Constructor
-    private GsmDataConnection(GSMPhone phone, String name, RetryManager rm) {
-        super(phone, name, rm);
+    private GsmDataConnection(PhoneBase phone, String name, int id, RetryManager rm) {
+        super(phone, name, id, rm);
     }
 
     /**
@@ -49,15 +53,14 @@
      * @param rm the RetryManager
      * @return GsmDataConnection that was created.
      */
-    static GsmDataConnection makeDataConnection(GSMPhone phone, int id, RetryManager rm) {
+    static GsmDataConnection makeDataConnection(PhoneBase phone, int id, RetryManager rm) {
         synchronized (mCountLock) {
             mCount += 1;
         }
-        GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount, rm);
+        GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount,
+                id, rm);
         gsmDc.start();
         if (DBG) gsmDc.log("Made " + gsmDc.getName());
-        gsmDc.mId = id;
-        gsmDc.mRetryMgr = rm;
         return gsmDc;
     }
 
@@ -102,11 +105,29 @@
 
         phone.mCM.setupDataCall(
                 Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
-                Integer.toString(RILConstants.DATA_PROFILE_DEFAULT),
-                apn.apn, apn.user, apn.password, Integer.toString(authType),
+                Integer.toString(mProfileId),
+                apn.apn, apn.user, apn.password,
+                Integer.toString(authType),
                 protocol, msg);
     }
 
+    public void setProfileId(int profileId) {
+        mProfileId = profileId;
+    }
+
+    public int getProfileId() {
+        return mProfileId;
+    }
+
+    public int getCid() {
+        // 'cid' has been defined in parent class
+        return cid;
+    }
+
+    public void setActiveApnType(String apnType) {
+        mActiveApnType = apnType;
+    }
+
     @Override
     protected void clearSettings() {
         super.clearSettings();
@@ -150,17 +171,35 @@
     }
 
     private void setHttpProxy(String httpProxy, String httpPort) {
-        if (httpProxy == null || httpProxy.length() == 0) {
-            phone.setSystemProperty("net.gprs.http-proxy", null);
-            return;
-        }
 
-        if (httpPort == null || httpPort.length() == 0) {
-            httpPort = "8080";     // Default to port 8080
-        }
+        if (DBG) log("set http proxy for"
+                + "' APN: '" + mActiveApnType
+                + "' proxy: '" + apn.proxy + "' port: '" + apn.port);
+        if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) {
+            if (httpProxy == null || httpProxy.length() == 0) {
+                phone.setSystemProperty("net.gprs.http-proxy", null);
+                return;
+            }
 
-        phone.setSystemProperty("net.gprs.http-proxy",
-                "http://" + httpProxy + ":" + httpPort + "/");
+            if (httpPort == null || httpPort.length() == 0) {
+                httpPort = "8080";     // Default to port 8080
+            }
+
+            phone.setSystemProperty("net.gprs.http-proxy",
+                    "http://" + httpProxy + ":" + httpPort + "/");
+        } else {
+            if (httpProxy == null || httpProxy.length() == 0) {
+                phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null);
+                return;
+            }
+
+            if (httpPort == null || httpPort.length() == 0) {
+                httpPort = "8080";  // Default to port 8080
+            }
+
+            phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType,
+                    "http://" + httpProxy + ":" + httpPort + "/");
+        }
     }
 
     private boolean isIpAddress(String address) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index c57f2f1..fa04e0f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -22,11 +22,14 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.ProxyProperties;
 import android.net.TrafficStats;
 import android.net.Uri;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
 import android.os.AsyncResult;
 import android.os.Message;
 import android.os.SystemClock;
@@ -36,24 +39,32 @@
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
+import android.preference.PreferenceManager;
 
 import com.android.internal.R;
+import com.android.internal.telephony.ApnContext;
 import com.android.internal.telephony.ApnSetting;
 import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.RetryManager;
 import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.RILConstants;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.HashMap;
 
 /**
@@ -62,7 +73,6 @@
 public final class GsmDataConnectionTracker extends DataConnectionTracker {
     protected final String LOG_TAG = "GSM";
 
-    private GSMPhone mGsmPhone;
     /**
      * Handles changes to the APN db.
      */
@@ -100,22 +110,15 @@
      */
     private ArrayList<ApnSetting> mAllApns = null;
 
-    /**
-     * waitingApns holds all apns that are waiting to be connected
-     *
-     * It is a subset of allApns and has the same format
-     */
-    private ArrayList<ApnSetting> mWaitingApns = null;
-    private int mWaitingApnsPermanentFailureCountDown = 0;
     private ApnSetting mPreferredApn = null;
 
-      /** The DataConnection being setup */
-    private GsmDataConnection mPendingDataConnection;
-
     /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
     private HashMap<String, Integer> mApnToDataConnectionId =
                                     new HashMap<String, Integer>();
 
+    /** Phone.APN_TYPE_* ===> ApnContext */
+    private ConcurrentHashMap<String, ApnContext> mApnContexts;
+
     /** Is packet service restricted by network */
     private boolean mIsPsRestricted = false;
 
@@ -124,32 +127,55 @@
     private static final int POLL_PDP_MILLIS = 5 * 1000;
 
     private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
+    private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "type";
 
     static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
     static final String APN_ID = "apn_id";
     private boolean canSetPreferApn = false;
 
+    @Override
+    protected void onActionIntentReconnectAlarm(Intent intent) {
+        log("GPRS reconnect alarm. Previous state was " + mState);
+
+        String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+        String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
+        ApnContext apnContext = mApnContexts.get(type);
+        if (apnContext != null) {
+            apnContext.setReason(reason);
+            if (apnContext.getState() == State.FAILED) {
+                Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+                msg.arg1 = 0; // tearDown is false
+                msg.obj = (ApnContext)apnContext;
+                sendMessage(msg);
+            }
+            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
+        }
+    }
+
     /** Watches for changes to the APN db. */
     private ApnChangeObserver mApnObserver;
 
     //***** Constructor
 
-    GsmDataConnectionTracker(GSMPhone p) {
+    public GsmDataConnectionTracker(PhoneBase p) {
         super(p);
-        mGsmPhone = p;
 
         p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
         p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
-        p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
-        p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
-        p.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
-        p.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
-        p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
-        p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
-        p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
-        p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
+        p.getCallTracker().registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+        p.getCallTracker().registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+        p.getServiceStateTracker().registerForDataConnectionAttached(this,
+                EVENT_DATA_CONNECTION_ATTACHED, null);
+        p.getServiceStateTracker().registerForDataConnectionDetached(this,
+                EVENT_DATA_CONNECTION_DETACHED, null);
+        p.getServiceStateTracker().registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+        p.getServiceStateTracker().registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+        p.getServiceStateTracker().registerForPsRestrictedEnabled(this,
+                EVENT_PS_RESTRICT_ENABLED, null);
+        p.getServiceStateTracker().registerForPsRestrictedDisabled(this,
+                EVENT_PS_RESTRICT_DISABLED, null);
 
         mDataConnectionTracker = this;
         mResolver = mPhone.getContext().getContentResolver();
@@ -159,7 +185,8 @@
                 Telephony.Carriers.CONTENT_URI, true, mApnObserver);
 
         /** Create the default connection */
-        createDataConnection(Phone.APN_TYPE_DEFAULT);
+        mApnContexts = new ConcurrentHashMap<String, ApnContext>();
+        initApncontextsAndDataConnection();
         broadcastMessenger();
     }
 
@@ -170,22 +197,44 @@
         //Unregister for all events
         mPhone.mCM.unregisterForAvailable(this);
         mPhone.mCM.unregisterForOffOrNotAvailable(this);
-        mGsmPhone.mSIMRecords.unregisterForRecordsLoaded(this);
+        mPhone.mSIMRecords.unregisterForRecordsLoaded(this);
         mPhone.mCM.unregisterForDataNetworkStateChanged(this);
-        mGsmPhone.mCT.unregisterForVoiceCallEnded(this);
-        mGsmPhone.mCT.unregisterForVoiceCallStarted(this);
-        mGsmPhone.mSST.unregisterForGprsAttached(this);
-        mGsmPhone.mSST.unregisterForGprsDetached(this);
-        mGsmPhone.mSST.unregisterForRoamingOn(this);
-        mGsmPhone.mSST.unregisterForRoamingOff(this);
-        mGsmPhone.mSST.unregisterForPsRestrictedEnabled(this);
-        mGsmPhone.mSST.unregisterForPsRestrictedDisabled(this);
+        mPhone.getCallTracker().unregisterForVoiceCallEnded(this);
+        mPhone.getCallTracker().unregisterForVoiceCallStarted(this);
+        mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(this);
+        mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(this);
+        mPhone.getServiceStateTracker().unregisterForRoamingOn(this);
+        mPhone.getServiceStateTracker().unregisterForRoamingOff(this);
+        mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this);
+        mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
 
         mPhone.getContext().getContentResolver().unregisterContentObserver(this.mApnObserver);
+        mApnContexts.clear();
 
         destroyDataConnections();
     }
 
+    /**
+     * The only circumstances under which we report that data connectivity is not
+     * possible are
+     * <ul>
+     * <li>Data is disallowed (roaming, power state, voice call, etc).</li>
+     * <li>The current data state is {@code DISCONNECTED} for a reason other than
+     * having explicitly disabled connectivity. In other words, data is not available
+     * because the phone is out of coverage or some like reason.</li>
+     * </ul>
+     * @return {@code true} if data connectivity is possible, {@code false} otherwise.
+     */
+    @Override
+    protected boolean isDataPossible() {
+        boolean possible = (isDataAllowed()
+                && getAnyDataEnabled() && (getOverallState() == State.CONNECTED));
+        if (!possible && DBG && isDataAllowed()) {
+            log("Data not possible.  No coverage: dataState = " + getOverallState());
+        }
+        return possible;
+    }
+
     @Override
     protected void finalize() {
         if(DBG) log("finalize");
@@ -196,41 +245,225 @@
         return INTENT_RECONNECT_ALARM;
     }
 
+    protected void initApncontextsAndDataConnection() {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+        boolean defaultEnabled = !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
+        // create default type context only if enabled
+        if (defaultEnabled) {
+            ApnContext apnContext = new ApnContext(Phone.APN_TYPE_DEFAULT, LOG_TAG);
+            mApnContexts.put(apnContext.getApnType(), apnContext);
+            createDataConnection(Phone.APN_TYPE_DEFAULT);
+        }
+    }
+
     @Override
-    protected void setState(State s) {
-        if (DBG) log ("setState: " + s);
-        if (mState != s) {
-            EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, mState.toString(), s.toString());
-            mState = s;
+    protected LinkProperties getLinkProperties(String apnType) {
+        ApnContext apnContext = mApnContexts.get(apnType);
+        if (apnContext != null && apnContext.getDataConnection() != null) {
+             if (DBG) log("get active pdp is not null, return link properites for " + apnType);
+             return apnContext.getDataConnection().getLinkProperties();
+        } else {
+            if (DBG) log("return new LinkProperties");
+            return new LinkProperties();
+        }
+    }
+
+    @Override
+    protected LinkCapabilities getLinkCapabilities(String apnType) {
+        ApnContext apnContext = mApnContexts.get(apnType);
+        if (apnContext!=null && apnContext.getDataConnection() != null) {
+             if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType);
+             return apnContext.getDataConnection().getLinkCapabilities();
+        } else {
+            if (DBG) log("return new LinkCapabilities");
+            return new LinkCapabilities();
+        }
+    }
+
+    @Override
+    // Return all active apn types
+    public synchronized String[] getActiveApnTypes() {
+        if (DBG) log("get all active apn types");
+        ArrayList<String> result = new ArrayList<String>();
+
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+        while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+                result.add(apnContext.getApnType());
         }
 
-        if (mState == State.FAILED) {
-            if (mWaitingApns != null)
-                mWaitingApns.clear(); // when tear down the connection and set to IDLE
+        return (String[])result.toArray(new String[0]);
+    }
+
+    @Override
+    /**
+     * Return DEFAULT APN due to the limit of the interface
+     */
+    public synchronized String getActiveApnString() {
+        if (DBG) log( "get default active apn string");
+        ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+        if (defaultApnContext != null && defaultApnContext.getApnSetting() != null) {
+            return defaultApnContext.getApnSetting().apn;
+        }
+        return null;
+    }
+
+    // Return active apn of specific apn type
+    public synchronized String getActiveApnString(String apnType) {
+        if (DBG) log( "get active apn string for type:" + apnType);
+        ApnContext apnContext = mApnContexts.get(apnType);
+        if (apnContext != null && apnContext.getApnSetting() != null) {
+            return apnContext.getApnSetting().apn;
+        }
+        return null;
+    }
+
+    // Return state of specific apn type
+    public synchronized State getState(String apnType) {
+        ApnContext apnContext = mApnContexts.get(apnType);
+        if (apnContext != null) {
+            return apnContext.getState();
+        }
+        return State.FAILED;
+    }
+
+    // Return state of overall
+    public State getOverallState() {
+        boolean isConnecting = false;
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+        while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+            if (apnContext.getState() == State.CONNECTED ||
+                    apnContext.getState() == State.DISCONNECTING) {
+                if (DBG) log("overall state is CONNECTED");
+                return State.CONNECTED;
+            }
+            else if (apnContext.getState() == State.CONNECTING
+                    || apnContext.getState() == State.INITING) {
+                isConnecting = true;
+            }
+        }
+        if (isConnecting) {
+            if (DBG) log( "overall state is CONNECTING");
+            return State.CONNECTING;
+        } else {
+            if (DBG) log( "overall state is IDLE");
+            return State.IDLE;
         }
     }
 
     /**
-     * The data connection is expected to be setup while device
-     *  1. has sim card
-     *  2. registered to gprs service
-     *  3. user doesn't explicitly disable data service
-     *  4. wifi is not on
+     * Ensure that we are connected to an APN of the specified type.
      *
-     * @return false while no data connection if all above requirements are met.
+     * @param type the APN type
+     * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
+     *         {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
+     *         broadcast will be sent by the ConnectivityManager when a
+     *         connection to the APN has been established.
      */
     @Override
-    public boolean isDataConnectionAsDesired() {
-        boolean roaming = mPhone.getServiceState().getRoaming();
+    public synchronized int enableApnType(String apnType) {
+        if (DBG) log("calling enableApnType with type:" + apnType);
 
-        if (mGsmPhone.mSIMRecords.getRecordsLoaded() &&
-                mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
-                (!roaming || getDataOnRoamingEnabled()) &&
-            !mIsWifiConnected &&
-            !mIsPsRestricted ) {
-            return (mState == State.CONNECTED);
+        if (!isApnTypeAvailable(apnType)) {
+            if (DBG) log("type not available");
+            return Phone.APN_TYPE_NOT_AVAILABLE;
         }
-        return true;
+
+        ApnContext apnContext = mApnContexts.get(apnType);
+        if (apnContext==null) {
+            // Is there a Proxy type for this?
+            apnContext = getProxyActiveApnType(apnType);
+            if (apnContext != null ) {
+                notifyApnIdUpToCurrent(Phone.REASON_APN_SWITCHED, apnContext, apnType);
+                return Phone.APN_REQUEST_STARTED;
+            }
+            apnContext = new ApnContext(apnType, LOG_TAG);
+            if (DBG) log("New apn type context for type "+apnType);
+            mApnContexts.put(apnType, apnContext);
+        }
+
+        // If already active, return
+        log("enableApnType(" + apnType + ")" + ", mState(" + apnContext.getState() + ")");
+
+        if (apnContext.getState() == State.INITING) {
+            if (DBG) log("return APN_REQUEST_STARTED");
+            return Phone.APN_REQUEST_STARTED;
+        }
+        else if (apnContext.getState() == State.CONNECTED) {
+            if (DBG) log("return APN_ALREADY_ACTIVE");
+            return Phone.APN_ALREADY_ACTIVE;
+        }
+        else if (apnContext.getState() == State.DISCONNECTING) {
+            if (DBG) log("requested APN while disconnecting");
+            apnContext.setPendingAction(ApnContext.PENDING_ACTION_RECONNECT);
+            return Phone.APN_REQUEST_STARTED;
+        }
+
+        if (DBG) log("new apn request for type " + apnType + " is to be handled");
+        sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN, apnContext));
+        if (DBG) log("return APN_REQUEST_STARTED");
+        return Phone.APN_REQUEST_STARTED;
+    }
+
+    // Returns for ex: if HIGHPRI is supported by DEFAULT
+    public ApnContext getProxyActiveApnType(String type) {
+
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+
+        while(it.hasNext()) {
+            ApnContext apnContext = it.next();
+            if (apnContext.getApnSetting() != null && mActiveApn.canHandleType(type))
+            return apnContext;
+        }
+        return null;
+    }
+
+    // A new APN has gone active and needs to send events to catch up with the
+    // current condition
+    private void notifyApnIdUpToCurrent(String reason, ApnContext apnContext, String type) {
+        switch (apnContext.getState()) {
+            case IDLE:
+            case INITING:
+                break;
+            case CONNECTING:
+            case SCANNING:
+                mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTING);
+                break;
+            case CONNECTED:
+            case DISCONNECTING:
+                mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTING);
+                mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTED);
+                break;
+        }
+    }
+
+    @Override
+    public synchronized int disableApnType(String type) {
+        if (DBG) log("calling disableApnType with type:" + type);
+        ApnContext apnContext = mApnContexts.get(type);
+
+        if (apnContext != null) {
+            apnContext.setPendingAction(ApnContext.PENDING_ACTION_APN_DISABLE);
+
+            if (apnContext.getState() != State.IDLE && apnContext.getState() != State.FAILED) {
+                Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+                msg.arg1 = 1; // tearDown is true;
+                apnContext.setReason(Phone.REASON_DATA_DISABLED);
+                msg.obj = apnContext;
+                sendMessage(msg);
+                if (DBG) log("return APN_REQUEST_STARTED");
+                return Phone.APN_REQUEST_STARTED;
+            } else {
+                if (DBG) log("return APN_ALREADY_INACTIVE");
+                return Phone.APN_ALREADY_INACTIVE;
+            }
+
+        } else {
+            if (DBG)
+                log("no apn context was found, return APN_REQUEST_FAILED");
+            return Phone.APN_REQUEST_FAILED;
+        }
     }
 
     @Override
@@ -249,12 +482,53 @@
         return false;
     }
 
+    protected boolean isEnabled(String apnType) {
+        ApnContext apnContext = mApnContexts.get(apnType);
+        if (apnContext == null) return false;
+        if (apnContext.getState() == State.DISCONNECTING
+                && apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Report on whether data connectivity is enabled for any APN.
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    @Override
+    public synchronized boolean getAnyDataEnabled() {
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+
+        if (!(mInternalDataEnabled && mDataEnabled)) return false;
+        if (mApnContexts.isEmpty()) return false;
+        while (it.hasNext()) {
+            ApnContext apnContext= it.next();
+            // Make sure we dont have a context that going down
+            // and is explicitly disabled.
+            if (!(apnContext.getState() == State.DISCONNECTING
+                    && apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isDataAllowed(ApnContext apnContext) {
+        if(apnContext.getState() == State.DISCONNECTING
+                && apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
+            return false;
+        }
+        return isDataAllowed();
+    }
+
     //****** Called from ServiceStateTracker
     /**
      * Invoked when ServiceStateTracker observes a transition from GPRS
      * attach to detach.
      */
-    protected void onGprsDetached() {
+    protected void onDataConnectionDetached() {
         /*
          * We presently believe it is unnecessary to tear down the PDP context
          * when GPRS detaches, but we should stop the network polling.
@@ -263,27 +537,29 @@
         notifyDataConnection(Phone.REASON_GPRS_DETACHED);
     }
 
-    private void onGprsAttached() {
-        if (mState == State.CONNECTED) {
+    private void onDataConnectionAttached() {
+        if (getOverallState() == State.CONNECTED) {
             startNetStatPoll();
             notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
         } else {
-            if (mState == State.FAILED) {
-                cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
-                mRetryMgr.resetRetryCount();
+            // Only check for default APN state
+            ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+            if (defaultApnContext.getState() == State.FAILED) {
+                cleanUpConnection(false, defaultApnContext);
+                defaultApnContext.getDataConnection().resetRetryCount();
             }
-            trySetupData(Phone.REASON_GPRS_ATTACHED);
+            trySetupData(Phone.REASON_GPRS_ATTACHED, Phone.APN_TYPE_DEFAULT);
         }
     }
 
     @Override
     protected boolean isDataAllowed() {
-        int gprsState = mGsmPhone.mSST.getCurrentGprsState();
-        boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
+        int gprsState = mPhone.getServiceStateTracker().getCurrentDataConnectionState();
+        boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
 
         boolean allowed =
                     (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
-                    mGsmPhone.mSIMRecords.getRecordsLoaded() &&
+                    mPhone.mSIMRecords.getRecordsLoaded() &&
                     mPhone.getState() == Phone.State.IDLE &&
                     mInternalDataEnabled &&
                     (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
@@ -294,7 +570,7 @@
             if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
                 reason += " - gprs= " + gprsState;
             }
-            if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
+            if (!mPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
             if (mPhone.getState() != Phone.State.IDLE) {
                 reason += " - PhoneState= " + mPhone.getState();
             }
@@ -309,94 +585,198 @@
         return allowed;
     }
 
-    private boolean trySetupData(String reason) {
-        if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
+    private boolean trySetupData(String reason, String type) {
+        if (DBG)
+            log("***trySetupData for type:" + type+" due to " + (reason == null ? "(unspecified)" : reason));
+        log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
 
+        if (type == null) {
+            type = Phone.APN_TYPE_DEFAULT;
+        }
+
+        ApnContext apnContext = mApnContexts.get(type);
+
+        if (apnContext == null ){
+            if (DBG) log("***new apn context for type:" + type);
+            apnContext = new ApnContext(type, LOG_TAG);
+            if (apnContext == null) {
+                if (DBG) log("***new apn context failed ");
+                return false;
+            }
+            mApnContexts.put(type, apnContext);
+        }
+        apnContext.setReason(reason);
+
+        return trySetupData(apnContext);
+
+    }
+
+    @Override
+    protected void setState(State s) {
+        if (DBG) log("setState should not be used in GSM" + s);
+    }
+
+    private boolean trySetupData(ApnContext apnContext) {
+
+        if (DBG)
+            log("trySetupData for type:" + apnContext.getApnType() +
+                " due to " + apnContext.getReason());
         log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
 
         if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
-            setState(State.CONNECTED);
-            notifyDataConnection(reason);
+            apnContext.setState(State.CONNECTED);
+            mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
 
             log("(fix?) We're on the simulator; assuming data is connected");
             return true;
         }
 
-        int gprsState = mGsmPhone.mSST.getCurrentGprsState();
-        boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
+        boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
 
-        if (((mState == State.IDLE) || (mState == State.SCANNING)) &&
-                isDataAllowed() && getAnyDataEnabled()) {
+        if ((apnContext.getState() == State.IDLE || apnContext.getState() == State.SCANNING) &&
+                isDataAllowed(apnContext) && getAnyDataEnabled()) {
 
-            if (mState == State.IDLE) {
-                mWaitingApns = buildWaitingApns(mRequestedApnType);
-                mWaitingApnsPermanentFailureCountDown = mWaitingApns.size();
-                if (mWaitingApns.isEmpty()) {
+            if (apnContext.getState() == State.IDLE) {
+                ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
+                if (waitingApns.isEmpty()) {
                     if (DBG) log("No APN found");
-                    notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
-                    notifyOffApnsOfAvailability(reason, false);
+                    notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
+                    notifyOffApnsOfAvailability(apnContext.getReason(), false);
                     return false;
                 } else {
-                    log ("Create from allApns : " + apnListToString(mAllApns));
+                    apnContext.setWaitingApns(waitingApns);
+                    log ("Create from mAllApns : " + apnListToString(mAllApns));
                 }
             }
 
             if (DBG) {
-                log ("Setup waitngApns : " + apnListToString(mWaitingApns));
+                log ("Setup watingApns : " + apnListToString(apnContext.getWaitingApns()));
             }
-            boolean retValue = setupData(reason);
-            notifyOffApnsOfAvailability(reason, retValue);
+            // apnContext.setReason(apnContext.getReason());
+            boolean retValue = setupData(apnContext);
+            notifyOffApnsOfAvailability(apnContext.getReason(), retValue);
             return retValue;
         } else {
-            notifyOffApnsOfAvailability(reason, false);
+            // TODO: check the condition.
+            if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)
+                && (apnContext.getState() == State.IDLE
+                    || apnContext.getState() == State.SCANNING))
+                mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+            notifyOffApnsOfAvailability(apnContext.getReason(), false);
             return false;
         }
     }
 
+    @Override
+    // Disabled apn's still need avail/unavail notificiations - send them out
+    protected void notifyOffApnsOfAvailability(String reason, boolean availability) {
+        if (mAvailability == availability) return;
+        mAvailability = availability;
+
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+        while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+            // FIXME: Dont understand why this needs to be done!!
+            // This information is not available (DISABLED APNS)
+            if (false) {
+                if (DBG) log("notify disconnected for type:" + apnContext.getApnType());
+                mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
+                                            apnContext.getApnType(),
+                                            Phone.DataState.DISCONNECTED);
+            }
+        }
+    }
+
+    /**
+     * If tearDown is true, this only tears down a CONNECTED session. Presently,
+     * there is no mechanism for abandoning an INITING/CONNECTING session,
+     * but would likely involve cancelling pending async requests or
+     * setting a flag or new state to ignore them when they came in
+     * @param tearDown true if the underlying GsmDataConnection should be
+     * disconnected.
+     * @param reason reason for the clean up.
+     */
+    protected void cleanUpAllConnections(boolean tearDown, String reason) {
+        if (DBG) log("Clean up all connections due to " + reason);
+
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+        while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+                apnContext.setReason(reason);
+            cleanUpConnection(tearDown, apnContext);
+        }
+
+        stopNetStatPoll();
+        // TODO: Do we need mRequestedApnType?
+        mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+    }
+
     /**
      * Cleanup all connections.
      *
      * TODO: Cleanup only a specified connection passed as a parameter.
+     *       Also, make sure when you clean up a conn, if it is last apply
+     *       logic as though it is cleanupAllConnections
      *
      * @param tearDown true if the underlying DataConnection should be disconnected.
      * @param reason for the clean up.
      */
-    private void cleanUpConnection(boolean tearDown, String reason) {
-        if (DBG) log("Clean up connection due to " + reason);
+
+    @Override
+    protected void onCleanUpAllConnections() {
+        cleanUpAllConnections(true, null);
+    }
+
+    private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
+
+        if (apnContext == null) {
+            if (DBG) log("apn context is null");
+            return;
+        }
+
+        if (DBG) log("Clean up connection due to " + apnContext.getReason());
 
         // Clear the reconnect alarm, if set.
-        if (mReconnectIntent != null) {
+        if (apnContext.getReconnectIntent() != null) {
             AlarmManager am =
                 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-            am.cancel(mReconnectIntent);
-            mReconnectIntent = null;
+            am.cancel(apnContext.getReconnectIntent());
+            apnContext.setReconnectIntent(null);
         }
 
-        setState(State.DISCONNECTING);
-
-        boolean notificationDeferred = false;
-        for (DataConnection conn : mDataConnections.values()) {
-            if (tearDown) {
-                if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
-                conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
-                        conn.getDataConnectionId(), 0, reason));
-                notificationDeferred = true;
-            } else {
-                if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
-                conn.resetSynchronously();
-                notificationDeferred = false;
-            }
+        if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
+            if (DBG) log("state is in " + apnContext.getState());
+            return;
         }
-        stopNetStatPoll();
 
-        if (!notificationDeferred) {
-            if (DBG) log("cleanupConnection: !notificationDeferred");
-            gotoIdleAndNotifyDataConnection(reason);
+        if (apnContext.getState() == State.FAILED) {
+            if (DBG) log("state is in FAILED");
+            apnContext.setState(State.IDLE);
+            return;
+        }
+
+        GsmDataConnection pdp = apnContext.getDataConnection();
+        if (tearDown && pdp!=null) {
+            apnContext.setState(State.DISCONNECTING);
+            Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+            pdp.disconnect(msg);
+            return;
+        } else if (pdp != null) {
+            pdp.clearSettings();
+        }
+
+        if (!tearDown) {
+            apnContext.setState(State.IDLE);
+            mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+        }
+        if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
+           mApnContexts.remove(apnContext.getApnType());
         }
     }
 
+
     /**
      * @param types comma delimited list of APN types
      * @return array of APN types
@@ -453,27 +833,64 @@
         return null;
     }
 
-    private boolean setupData(String reason) {
-        ApnSetting apn;
-        GsmDataConnection gdc;
+    protected GsmDataConnection findReadyDataConnection(ApnSetting apn) {
+        if (DBG)
+            log("findReadyDataConnection for apn string <" +
+                (apn!=null?(apn.toString()):"null") +">");
+        for (DataConnection conn : mDataConnections.values()) {
+            GsmDataConnection dc = (GsmDataConnection) conn;
+            if (DBG) log("dc apn string <" +
+                         (dc.getApn() != null ? (dc.getApn().toString()) : "null") + ">");
+            if (dc.getApn() != null && apn != null
+                && dc.getApn().toString().equals(apn.toString())) {
+                return dc;
+            }
+        }
+        return null;
+    }
 
-        apn = getNextApn();
-        if (apn == null) return false;
-        gdc = findFreeDataConnection();
-        if (gdc == null) {
+
+    private boolean setupData(ApnContext apnContext) {
+        if (DBG) log("enter setupData!");
+        ApnSetting apn;
+        GsmDataConnection dc;
+
+        int profileId = getApnProfileID(apnContext.getApnType());
+        apn = apnContext.getNextApn();
+        if (apn == null) {
+            if (DBG) log("setupData: return for no apn found!");
+            return false;
+        }
+
+        dc = findReadyDataConnection(apn);
+
+        if (dc == null) {
+            if (DBG) log("setupData: No ready GsmDataConnection found!");
+            // TODO: When allocating you are mapping type to id. If more than 1 free,
+            // then could findFreeDataConnection get the wrong one??
+            dc = findFreeDataConnection();
+        }
+
+        if (dc == null) {
             if (DBG) log("setupData: No free GsmDataConnection found!");
             return false;
         }
-        mActiveApn = apn;
-        mPendingDataConnection = gdc;
+
+        apnContext.setApnSetting(apn);
+        apnContext.setDataConnection(dc);
+        dc.setProfileId( profileId );
+        dc.setActiveApnType(apnContext.getApnType());
 
         Message msg = obtainMessage();
         msg.what = EVENT_DATA_SETUP_COMPLETE;
-        msg.obj = reason;
-        gdc.connect(msg, apn);
+        msg.obj = apnContext;
 
-        setState(State.INITING);
-        notifyDataConnection(reason);
+        if (DBG) log("dc connect!");
+        dc.connect(msg, apn);
+
+        apnContext.setState(State.INITING);
+        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+        if (DBG) log("setupData: initing!");
         return true;
     }
 
@@ -498,24 +915,28 @@
      * Handles changes to the APN database.
      */
     private void onApnChanged() {
+        // TODO: How to handle when multiple APNs are active?
         boolean isConnected;
 
-        isConnected = (mState != State.IDLE && mState != State.FAILED);
+        ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+        isConnected = (defaultApnContext.getState() != State.IDLE
+                       && defaultApnContext.getState() != State.FAILED);
 
-        // The "current" may no longer be valid.  MMS depends on this to send properly.
-        mGsmPhone.updateCurrentCarrierInProvider();
+        if (mPhone instanceof GSMPhone) {
+            // The "current" may no longer be valid.  MMS depends on this to send properly. TBD
+            ((GSMPhone)mPhone).updateCurrentCarrierInProvider();
+        }
 
         // TODO: It'd be nice to only do this if the changed entrie(s)
         // match the current operator.
         createAllApnList();
-        if (mState != State.DISCONNECTING) {
-            cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
-            if (!isConnected) {
-                // reset reconnect timer
-                mRetryMgr.resetRetryCount();
-                mReregisterOnReconnectFailure = false;
-                trySetupData(Phone.REASON_APN_CHANGED);
-            }
+        if (DBG) log("onApnChanged clean all connections");
+        cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED);
+        if (!isConnected) {
+            // TODO: Won't work for multiple connections!!!!
+            defaultApnContext.getDataConnection().resetRetryCount();
+            defaultApnContext.setReason(Phone.REASON_APN_CHANGED);
+            trySetupData(defaultApnContext);
         }
     }
 
@@ -537,28 +958,46 @@
             return;
         }
 
-        if (mState == State.CONNECTED) {
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+        while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+            onDataStateChanged(dataCallStates, explicitPoll, apnContext);
+        }
+    }
+
+    private void onDataStateChanged (ArrayList<DataCallState> dataCallStates,
+                                     boolean explicitPoll,
+                                     ApnContext apnContext) {
+
+        if (apnContext == null) {
+            // Should not happen
+            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 (!dataCallStatesHasCID(dataCallStates, mCidActive)) {
+            if (!dataCallStatesHasCID(dataCallStates, apnContext.getDataConnection().getCid())) {
                 // It looks like the PDP context has deactivated.
                 // Tear everything down and try to reconnect.
 
-                log("PDP connection has dropped. Reconnecting");
+                Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
 
                 // Add an event log when the network drops PDP
+                int cid = -1;
                 GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
-                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
-                        loc != null ? loc.getCid() : -1,
+                if (loc != null) cid = loc.getCid();
+                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
                         TelephonyManager.getDefault().getNetworkType());
 
-                cleanUpConnection(true, null);
+                cleanUpConnection(true, apnContext);
                 return;
-            } else if (!dataCallStatesHasActiveCID(dataCallStates, mCidActive)) {
+            } else if (!dataCallStatesHasActiveCID(dataCallStates,
+                    apnContext.getDataConnection().getCid())) {
                 // Here, we only consider this authoritative if we asked for the
                 // PDP list. If it was an unsolicited response, we poll again
                 // to make sure everyone agrees on the initial state.
@@ -568,33 +1007,37 @@
                     mPhone.mCM.getPDPContextList(
                             this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
                 } else {
-                    log("PDP connection has dropped (active=false case). "
+                    Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
                                     + " Reconnecting");
 
                     // Log the network drop on the event log.
+                    int cid = -1;
                     GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
-                    EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
-                            loc != null ? loc.getCid() : -1,
+                    if (loc != null) cid = loc.getCid();
+                    EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
                             TelephonyManager.getDefault().getNetworkType());
 
-                    cleanUpConnection(true, null);
+                    cleanUpConnection(true, apnContext);
                 }
             }
         }
     }
 
-    private void notifyDefaultData(String reason) {
-        setState(State.CONNECTED);
-        notifyDataConnection(reason);
+    private void notifyDefaultData(ApnContext apnContext) {
+        if (DBG)
+            log("notifyDefaultData for type: " + apnContext.getApnType()
+                + ", reason:" + apnContext.getReason());
+        apnContext.setState(State.CONNECTED);
+        // setState(State.CONNECTED);
+        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
         startNetStatPoll();
         // reset reconnect timer
-        mRetryMgr.resetRetryCount();
-        mReregisterOnReconnectFailure = false;
+        apnContext.getDataConnection().resetRetryCount();
     }
 
+    // TODO: For multiple Active APNs not exactly sure how to do this.
     private void gotoIdleAndNotifyDataConnection(String reason) {
         if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
-        setState(State.IDLE);
         notifyDataConnection(reason);
         mActiveApn = null;
     }
@@ -608,18 +1051,18 @@
     }
 
     private void doRecovery() {
-        if (mState == State.CONNECTED) {
+        if (getOverallState() == State.CONNECTED) {
             int maxPdpReset = Settings.Secure.getInt(mResolver,
                     Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
                     DEFAULT_MAX_PDP_RESET_FAIL);
             if (mPdpResetCount < maxPdpReset) {
                 mPdpResetCount++;
                 EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
-                cleanUpConnection(true, Phone.REASON_PDP_RESET);
+                cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
             } else {
                 mPdpResetCount = 0;
                 EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
-                mGsmPhone.mSST.reRegisterNetwork(null);
+                mPhone.getServiceStateTracker().reRegisterNetwork(null);
             }
             // TODO: Add increasingly drastic recovery steps, eg,
             // reset the radio, reset the device.
@@ -628,7 +1071,7 @@
 
     @Override
     protected void startNetStatPoll() {
-        if (mState == State.CONNECTED && mNetStatPollEnabled == false) {
+        if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) {
             log("[DataConnection] Start poll NetStat");
             resetPollStats();
             mNetStatPollEnabled = true;
@@ -646,8 +1089,8 @@
     @Override
     protected void restartRadio() {
         log("************TURN OFF RADIO**************");
-        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
-        mGsmPhone.mSST.powerOffRadioSafely();
+        cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
+        mPhone.getServiceStateTracker().powerOffRadioSafely();
         /* Note: no need to call setRadioPower(true).  Assuming the desired
          * radio power state is still ON (as tracked by ServiceStateTracker),
          * ServiceStateTracker will call setRadioPower when it receives the
@@ -784,107 +1227,132 @@
         return retry;
     }
 
-    private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
-        if (mState == State.FAILED) {
-            /** TODO: Retrieve retry manager from connection itself */
-            if (!mRetryMgr.isRetryNeeded()) {
-                if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+    private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
+        if (apnContext == null) {
+            Log.d(LOG_TAG, "It is impossible");
+            return;
+        }
+        if (apnContext.getState() == State.FAILED) {
+            if (!apnContext.getDataConnection().isRetryNeeded()) {
+                if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)){
                     // if no more retries on a secondary APN attempt, tell the world and revert.
                     notifyDataConnection(Phone.REASON_APN_FAILED);
-                    onEnableApn(apnTypeToId(mRequestedApnType), DISABLED);
                     return;
                 }
                 if (mReregisterOnReconnectFailure) {
-                    // We've re-registered once now just retry forever.
-                    mRetryMgr.retryForeverUsingLastTimeout();
+                    // We've re-registerd once now just retry forever.
+                    apnContext.getDataConnection().retryForeverUsingLastTimeout();
                 } else {
-                    // Try to re-register to the network.
+                    // Try to Re-register to the network.
                     log("PDP activate failed, Reregistering to the network");
                     mReregisterOnReconnectFailure = true;
-                    mGsmPhone.mSST.reRegisterNetwork(null);
-                    mRetryMgr.resetRetryCount();
+                    mPhone.getServiceStateTracker().reRegisterNetwork(null);
+                    apnContext.getDataConnection().resetRetryCount();
                     return;
                 }
             }
 
-            int nextReconnectDelay = mRetryMgr.getRetryTimer();
+            int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
             log("PDP activate failed. Scheduling next attempt for "
                     + (nextReconnectDelay / 1000) + "s");
 
             AlarmManager am =
                 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
             Intent intent = new Intent(INTENT_RECONNECT_ALARM);
-            intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
-            mReconnectIntent = PendingIntent.getBroadcast(
-                    mPhone.getContext(), 0, intent, 0);
+            intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
+            // Should put an extra of apn type?
+            intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
+            apnContext.setReconnectIntent(PendingIntent.getBroadcast (
+                    mPhone.getContext(), 0, intent, 0));
             am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                     SystemClock.elapsedRealtime() + nextReconnectDelay,
-                    mReconnectIntent);
+                    apnContext.getReconnectIntent());
 
-            mRetryMgr.increaseRetryCount();
+            apnContext.getDataConnection().increaseRetryCount();
 
             if (!shouldPostNotification(lastFailCauseCode)) {
-                log("NOT Posting GPRS Unavailable notification "
+                Log.d(LOG_TAG, "NOT Posting GPRS Unavailable notification "
                                 + "-- likely transient error");
             } else {
-                notifyNoData(lastFailCauseCode);
+                notifyNoData(lastFailCauseCode, apnContext);
             }
         }
     }
 
-    private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode) {
-        setState(State.FAILED);
+    private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
+                              ApnContext apnContext) {
+        if (DBG) log( "notifyNoData for type:" + apnContext.getApnType());
+        apnContext.setState(State.FAILED);
+        if (lastFailCauseCode.isPermanentFail()
+            && (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) {
+            mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+        }
     }
 
     private void onRecordsLoaded() {
         createAllApnList();
-        if (mState == State.FAILED) {
-            cleanUpConnection(false, null);
+        ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+        if (defaultApnContext!=null ) {
+            defaultApnContext.setReason(Phone.REASON_SIM_LOADED);
+            if (defaultApnContext.getState() == State.FAILED) {
+                if (DBG) log("onRecordsLoaded clean connection");
+                cleanUpConnection(false, defaultApnContext);
+            }
+            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA,defaultApnContext ));
         }
-        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
     }
 
-    @Override
-    protected void onEnableNewApn() {
-        log("onEnableNewApn E");
+    protected void onEnableNewApn(ApnContext apnContext ) {
         // change our retry manager to use the appropriate numbers for the new APN
-        if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
+        log("onEnableNewApn with ApnContext E");
+        if (apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
             log("onEnableNewApn default type");
-            mRetryMgr = mPendingDataConnection.getRetryMgr();
-            mRetryMgr.resetRetryCount();
-        } else if (mApnToDataConnectionId.get(mRequestedApnType) == null) {
-            log("onEnableNewApn mRequestedApnType=" + mRequestedApnType +
+            ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+            defaultApnContext.getDataConnection().resetRetryCount();
+        } else if (mApnToDataConnectionId.get(apnContext.getApnType()) == null) {
+            log("onEnableNewApn ApnType=" + apnContext.getApnType() +
                     " missing, make a new connection");
-            int id = createDataConnection(mRequestedApnType);
-            mRetryMgr = mDataConnections.get(id).getRetryMgr();
-            mRetryMgr.resetRetryCount();
+            int id = createDataConnection(apnContext.getApnType());
+            mDataConnections.get(id).resetRetryCount();
         } else {
             log("oneEnableNewApn connection already exists, nothing to setup");
         }
 
         // TODO:  To support simultaneous PDP contexts, this should really only call
         // cleanUpConnection if it needs to free up a GsmDataConnection.
-        cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
-        log("onEnableNewApn X");
+        if (DBG) log("onEnableNewApn setup data");
+        if (apnContext.getState() == State.FAILED) {
+            if (DBG) log("previous state is FAILED, reset to IDLE");
+            apnContext.setState(State.IDLE);
+        }
+        trySetupData(apnContext);
+        log("onEnableNewApn with ApnContext X");
     }
 
     @Override
+    // TODO: We shouldnt need this.
     protected boolean onTrySetupData(String reason) {
-        return trySetupData(reason);
+        return trySetupData(reason, Phone.APN_TYPE_DEFAULT);
+    }
+
+    protected boolean onTrySetupData(ApnContext apnContext) {
+        return trySetupData(apnContext);
     }
 
     @Override
+    // TODO: Need to understand if more than DEFAULT is impacted?
     protected void onRoamingOff() {
-        trySetupData(Phone.REASON_ROAMING_OFF);
+        trySetupData(Phone.REASON_ROAMING_OFF, Phone.APN_TYPE_DEFAULT);
     }
 
     @Override
+    // TODO: Need to understand if more than DEFAULT is impacted?
     protected void onRoamingOn() {
         if (getDataOnRoamingEnabled()) {
-            trySetupData(Phone.REASON_ROAMING_ON);
+            trySetupData(Phone.REASON_ROAMING_ON, Phone.APN_TYPE_DEFAULT);
         } else {
             if (DBG) log("Tear down data connection on roaming.");
-            cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+            cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
         }
     }
 
@@ -893,13 +1361,13 @@
         if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
-            setState(State.CONNECTED);
+            // setState(State.CONNECTED);
             notifyDataConnection(null);
 
             log("We're on the simulator; assuming data is connected");
         }
 
-        if (mState != State.IDLE) {
+        if (getOverallState() != State.IDLE) {
             cleanUpConnection(true, null);
         }
     }
@@ -908,7 +1376,10 @@
     protected void onRadioOffOrNotAvailable() {
         // Make sure our reconnect delay starts at the initial value
         // next time the radio comes on
-        mRetryMgr.resetRetryCount();
+
+        for (DataConnection dc : mDataConnections.values()) {
+            dc.resetRetryCount();
+        }
         mReregisterOnReconnectFailure = false;
 
         if (mPhone.getSimulatedRadioControl() != null) {
@@ -917,28 +1388,30 @@
             log("We're on the simulator; assuming radio off is meaningless");
         } else {
             if (DBG) log("Radio is off and clean up all connection");
-            // TODO: Should we reset mRequestedApnType to "default"?
-            cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+            cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
         }
     }
 
     @Override
     protected void onDataSetupComplete(AsyncResult ar) {
-        /** TODO: Which connection is completing should be a parameter */
-        String reason = null;
-        if (ar.userObj instanceof String) {
-            reason = (String) ar.userObj;
+
+        ApnContext apnContext = null;
+
+        if(ar.userObj instanceof ApnContext){
+            apnContext = (ApnContext)ar.userObj;
         }
 
         if (ar.exception == null) {
-            if(DBG) {
-                log(String.format("onDataSetupComplete: success apn=%s", mWaitingApns.get(0).apn));
-            }
+            // Everything is setup
             // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
-            mLinkProperties = getLinkProperties(mPendingDataConnection);
-            mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
+            if (DBG) {
+                log(String.format("onDataSetupComplete: success apn=%s",
+                    apnContext.getWaitingApns().get(0).apn));
+            }
+            mLinkProperties = getLinkProperties(apnContext.getDataConnection());
+            mLinkCapabilities = getLinkCapabilities(apnContext.getDataConnection());
 
-            ApnSetting apn = mPendingDataConnection.getApn();
+            ApnSetting apn = apnContext.getDataConnection().getApn();
             if (apn.proxy != null && apn.proxy.length() != 0) {
                 try {
                     ProxyProperties proxy = new ProxyProperties(apn.proxy,
@@ -951,29 +1424,34 @@
             }
 
             // everything is setup
-            if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+            if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) {
                 SystemProperties.set("gsm.defaultpdpcontext.active", "true");
-                        if (canSetPreferApn && mPreferredApn == null) {
-                            log("PREFERRED APN is null");
-                            mPreferredApn = mActiveApn;
-                            setPreferredApn(mPreferredApn.id);
-                        }
+                if (canSetPreferApn && mPreferredApn == null) {
+                    log("PREFERED APN is null");
+                    mPreferredApn = apnContext.getApnSetting();
+                    if (mPreferredApn != null) {
+                        setPreferredApn(mPreferredApn.id);
+                    }
+                }
             } else {
                 SystemProperties.set("gsm.defaultpdpcontext.active", "false");
             }
-            notifyDefaultData(reason);
+            notifyDefaultData(apnContext);
 
             // TODO: For simultaneous PDP support, we need to build another
             // trigger another TRY_SETUP_DATA for the next APN type.  (Note
             // that the existing connection may service that type, in which
             // case we should try the next type, etc.
+            // I dont believe for simultaneous PDP you need to trigger. Each
+            // Connection should be independent and they can be setup simultaneously
+            // So, dont have to wait till one is finished.
         } else {
             GsmDataConnection.FailCause cause;
             cause = (GsmDataConnection.FailCause) (ar.result);
             if (DBG) {
                 String apnString;
                 try {
-                    apnString = mWaitingApns.get(0).apn;
+                    apnString = apnContext.getWaitingApns().get(0).apn;
                 } catch (Exception e) {
                     apnString = "<unknown>";
                 }
@@ -988,28 +1466,31 @@
             }
 
             // Count permanent failures and remove the APN we just tried
-            mWaitingApnsPermanentFailureCountDown -= cause.isPermanentFail() ? 1 : 0;
-            mWaitingApns.remove(0);
+            // TODO: Where is mWaitingApnsPermanentFailureCountDown initialized
+            if (cause.isPermanentFail())
+                apnContext.decPermFailCount();
+
+            apnContext.removeNextApn();
             if (DBG) log(String.format("onDataSetupComplete: mWaitingApns.size=%d" +
                             " mWaitingApnsPermanenatFailureCountDown=%d",
-                            mWaitingApns.size(), mWaitingApnsPermanentFailureCountDown));
+                            apnContext.getWaitingApns().size(), apnContext.getPermFailCount()));
 
             // See if there are more APN's to try
-            if (mWaitingApns.isEmpty()) {
-                if (mWaitingApnsPermanentFailureCountDown == 0) {
+            if (apnContext.getWaitingApns().isEmpty()) {
+                if (apnContext.getPermFailCount() == 0) {
                     if (DBG) log("onDataSetupComplete: Permanent failures stop retrying");
-                    notifyNoData(cause);
+                    apnContext.setState(State.FAILED);
                     notifyDataConnection(Phone.REASON_APN_FAILED);
                 } else {
                     if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
-                    startDelayedRetry(cause, reason);
+                    startDelayedRetry(cause, apnContext);
                 }
             } else {
                 if (DBG) log("onDataSetupComplete: Try next APN");
-                setState(State.SCANNING);
+                apnContext.setState(State.SCANNING);
                 // Wait a bit before trying the next APN, so that
                 // we're not tying up the RIL command channel
-                sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason), APN_DELAY_MILLIS);
+                sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext), APN_DELAY_MILLIS);
             }
         }
     }
@@ -1019,16 +1500,31 @@
      */
     @Override
     protected void onDisconnectDone(int connId, AsyncResult ar) {
+        ApnContext apnContext = null;
+
         if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
-        String reason = null;
-        if (ar.userObj instanceof String) {
-           reason = (String) ar.userObj;
+        if (ar.userObj instanceof ApnContext) {
+            apnContext = (ApnContext) ar.userObj;
         }
-        setState(State.IDLE);
-        notifyDataConnection(reason);
-        mActiveApn = null;
-        if (retryAfterDisconnected(reason)) {
-            trySetupData(reason);
+
+        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+        // Check if APN disabled.
+        if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
+           mApnContexts.remove(apnContext.getApnType());
+           return;
+        }
+
+        apnContext.setState(State.IDLE);
+        apnContext.setApnSetting(null);
+        if (TextUtils.equals(apnContext.getApnType(), Phone.APN_TYPE_DEFAULT)
+            && retryAfterDisconnected(apnContext.getReason())) {
+            SystemProperties.set("gsm.defaultpdpcontext.active", "false");
+            trySetupData(apnContext);
+        }
+        else if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_RECONNECT)
+        {
+            apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE);
+            trySetupData(apnContext);
         }
     }
 
@@ -1046,7 +1542,7 @@
     }
 
     protected void onPollPdp() {
-        if (mState == State.CONNECTED) {
+        if (getOverallState() == State.CONNECTED) {
             // only poll when connected
             mPhone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
             sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
@@ -1055,7 +1551,7 @@
 
     @Override
     protected void onVoiceCallStarted() {
-        if (mState == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+        if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
             stopNetStatPoll();
             notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
         }
@@ -1063,8 +1559,8 @@
 
     @Override
     protected void onVoiceCallEnded() {
-        if (mState == State.CONNECTED) {
-            if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+        if (isConnected()) {
+            if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 startNetStatPoll();
                 notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
             } else {
@@ -1073,16 +1569,43 @@
             }
         } else {
             // reset reconnect timer
-            mRetryMgr.resetRetryCount();
+            ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+            defaultApnContext.getDataConnection().resetRetryCount();
             mReregisterOnReconnectFailure = false;
             // in case data setup was attempted when we were on a voice call
-            trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+            trySetupData(Phone.REASON_VOICE_CALL_ENDED, Phone.APN_TYPE_DEFAULT);
         }
     }
 
     @Override
-    protected void onCleanUpConnection(boolean tearDown, String reason) {
-        cleanUpConnection(tearDown, reason);
+    protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) {
+        if (DBG) log("onCleanUpConnection");
+        ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
+        cleanUpConnection(tearDown, apnContext);
+    }
+
+    protected boolean isConnected() {
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+         while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+            if (apnContext.getState() == State.CONNECTED) {
+            return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    protected void notifyDataConnection(String reason) {
+        if (DBG) log("notify all enabled connection for:" + reason);
+        Iterator<ApnContext> it = mApnContexts.values().iterator();
+        while (it.hasNext()) {
+            ApnContext apnContext = it.next();
+            if (DBG) log("notify for type:"+apnContext.getApnType());
+            mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
+                    apnContext.getApnType());
+        }
+        notifyDataAvailability(reason);
     }
 
     /**
@@ -1091,7 +1614,7 @@
      */
     private void createAllApnList() {
         mAllApns = new ArrayList<ApnSetting>();
-        String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
+        String operator = mPhone.mSIMRecords.getSIMOperatorNumeric();
 
         if (operator != null) {
             String selection = "numeric = '" + operator + "'";
@@ -1110,7 +1633,8 @@
         if (mAllApns.isEmpty()) {
             if (DBG) log("No APN found for carrier: " + operator);
             mPreferredApn = null;
-            notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
+            // TODO: What is the right behaviour?
+            //notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
         } else {
             mPreferredApn = getPreferredApn();
             log("Get PreferredAPN");
@@ -1147,7 +1671,7 @@
         }
 
         int id = mUniqueIdGenerator.getAndIncrement();
-        DataConnection conn = GsmDataConnection.makeDataConnection(mGsmPhone, id, rm);
+        DataConnection conn = GsmDataConnection.makeDataConnection(mPhone, id, rm);
         mDataConnections.put(id, conn);
         mApnToDataConnectionId.put(apnType, id);
 
@@ -1191,7 +1715,7 @@
             return apnList;
         }
 
-        String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
+        String operator = mPhone.mSIMRecords.getSIMOperatorNumeric();
 
         if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
             if (canSetPreferApn && mPreferredApn != null) {
@@ -1218,22 +1742,6 @@
         return apnList;
     }
 
-    /**
-     * Get next apn in waitingApns
-     * @return the first apn found in waitingApns, null if none
-     */
-    private ApnSetting getNextApn() {
-        ArrayList<ApnSetting> list = mWaitingApns;
-        ApnSetting apn = null;
-
-        if (list != null) {
-            if (!list.isEmpty()) {
-                apn = list.get(0);
-            }
-        }
-        return apn;
-    }
-
     private String apnListToString (ArrayList<ApnSetting> apns) {
         StringBuilder result = new StringBuilder();
         for (int i = 0, size = apns.size(); i < size; i++) {
@@ -1244,9 +1752,9 @@
         return result.toString();
     }
 
-    private void startDelayedRetry(GsmDataConnection.FailCause cause, String reason) {
-        notifyNoData(cause);
-        reconnectAfterFail(cause, reason);
+    private void startDelayedRetry(GsmDataConnection.FailCause cause, ApnContext apnContext) {
+        notifyNoData(cause, apnContext);
+        reconnectAfterFail(cause, apnContext);
     }
 
     private void setPreferredApn(int pos) {
@@ -1302,7 +1810,7 @@
     public void handleMessage (Message msg) {
         if (DBG) log("GSMDataConnTrack handleMessage "+msg);
 
-        if (!mGsmPhone.mIsTheCurrentActivePhone) {
+        if (!mPhone.mIsTheCurrentActivePhone) {
             log("Ignore GSM msgs since GSM phone is inactive");
             return;
         }
@@ -1312,12 +1820,20 @@
                 onRecordsLoaded();
                 break;
 
-            case EVENT_GPRS_DETACHED:
-                onGprsDetached();
+        case EVENT_ENABLE_NEW_APN:
+                ApnContext apnContext = null;
+                if (msg.obj instanceof ApnContext) {
+                    apnContext = (ApnContext)msg.obj;
+                }
+                onEnableNewApn(apnContext);
                 break;
 
-            case EVENT_GPRS_ATTACHED:
-                onGprsAttached();
+            case EVENT_DATA_CONNECTION_DETACHED:
+                onDataConnectionDetached();
+                break;
+
+            case EVENT_DATA_CONNECTION_ATTACHED:
+                onDataConnectionAttached();
                 break;
 
             case EVENT_DATA_STATE_CHANGED:
@@ -1363,18 +1879,37 @@
                  */
                 log("[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
                 mIsPsRestricted  = false;
-                if (mState == State.CONNECTED) {
+                if (isConnected()) {
                     startNetStatPoll();
                 } else {
+                    // TODO: Should all PDN states be checked to fail?
                     if (mState == State.FAILED) {
-                        cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
-                        mRetryMgr.resetRetryCount();
+                        cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED);
+                        resetAllRetryCounts();
                         mReregisterOnReconnectFailure = false;
                     }
-                    trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
+                    trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, Phone.APN_TYPE_DEFAULT);
+                }
+                break;
+            case EVENT_TRY_SETUP_DATA:
+                if (msg.obj instanceof ApnContext) {
+                    onTrySetupData((ApnContext)msg.obj);
+                } else {
+                    if (msg.obj instanceof String) {
+                        onTrySetupData((String)msg.obj);
+                    }
                 }
                 break;
 
+            case EVENT_CLEAN_UP_CONNECTION:
+                boolean tearDown = (msg.arg1 == 0) ? false : true;
+                if (msg.obj instanceof ApnContext) {
+                    cleanUpConnection(tearDown, (ApnContext)msg.obj);
+                } else {
+                    Log.e(LOG_TAG,
+                          "[GsmDataConnectionTracker] connectpion cleanup request w/o apn context");
+                }
+                break;
             default:
                 // handle the message in the super class DataConnectionTracker
                 super.handleMessage(msg);
@@ -1382,6 +1917,18 @@
         }
     }
 
+    protected int getApnProfileID(String apnType) {
+        if (TextUtils.equals(apnType, Phone.APN_TYPE_IMS)) {
+            return RILConstants.DATA_PROFILE_IMS;
+        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_FOTA)) {
+            return RILConstants.DATA_PROFILE_FOTA;
+        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_CBS)) {
+            return RILConstants.DATA_PROFILE_CBS;
+        } else {
+            return RILConstants.DATA_PROFILE_DEFAULT;
+        }
+    }
+
     @Override
     protected void log(String s) {
         Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index f576b4e..21a12f1 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -99,7 +99,7 @@
 
     /** {@inheritDoc} */
     @Override
-    protected int dispatchMessage(SmsMessageBase smsb) {
+    public int dispatchMessage(SmsMessageBase smsb) {
 
         // If sms is null, means there was a parsing error.
         if (smsb == null) {
@@ -383,7 +383,7 @@
 
     /** {@inheritDoc} */
     @Override
-    protected void activateCellBroadcastSms(int activate, Message response) {
+    public void activateCellBroadcastSms(int activate, Message response) {
         // Unless CBS is implemented for GSM, this point should be unreachable.
         Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
         response.recycle();
@@ -391,7 +391,7 @@
 
     /** {@inheritDoc} */
     @Override
-    protected void getCellBroadcastSmsConfig(Message response){
+    public void getCellBroadcastSmsConfig(Message response){
         // Unless CBS is implemented for GSM, this point should be unreachable.
         Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
         response.recycle();
@@ -399,7 +399,7 @@
 
     /** {@inheritDoc} */
     @Override
-    protected  void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+    public  void setCellBroadcastConfig(int[] configValuesArray, Message response) {
         // Unless CBS is implemented for GSM, this point should be unreachable.
         Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
         response.recycle();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index ac83808..277980a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -23,6 +23,7 @@
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RestrictedState;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
@@ -75,7 +76,6 @@
     GsmCellLocation cellLoc;
     GsmCellLocation newCellLoc;
     int mPreferredNetworkType;
-    RestrictedState rs;
 
     private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
     private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
@@ -107,11 +107,6 @@
      */
     private boolean mEmergencyOnly = false;
 
-    private RegistrantList gprsAttachedRegistrants = new RegistrantList();
-    private RegistrantList gprsDetachedRegistrants = new RegistrantList();
-    private RegistrantList psRestrictEnabledRegistrants = new RegistrantList();
-    private RegistrantList psRestrictDisabledRegistrants = new RegistrantList();
-
     /**
      * Sometimes we get the NITZ time before we know what country we
      * are in. Keep the time zone information from the NITZ string so
@@ -206,7 +201,6 @@
         newSS = new ServiceState();
         cellLoc = new GsmCellLocation();
         newCellLoc = new GsmCellLocation();
-        rs = new RestrictedState();
         mSignalStrength = new SignalStrength();
 
         PowerManager powerManager =
@@ -272,97 +266,6 @@
         return phone;
     }
 
-    /**
-     * Registration point for transition into GPRS attached.
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForGprsAttached(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        gprsAttachedRegistrants.add(r);
-
-        if (gprsState == ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForGprsAttached(Handler h) {
-        gprsAttachedRegistrants.remove(h);
-    }
-
-    void registerForNetworkAttach(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        networkAttachedRegistrants.add(r);
-
-        if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForNetworkAttach(Handler h) {
-        networkAttachedRegistrants.remove(h);
-    }
-
-    /**
-     * Registration point for transition into GPRS detached.
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForGprsDetached(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        gprsDetachedRegistrants.add(r);
-
-        if (gprsState == ServiceState.STATE_OUT_OF_SERVICE) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForGprsDetached(Handler h) {
-        gprsDetachedRegistrants.remove(h);
-    }
-
-    /**
-     * Registration point for transition into packet service restricted zone.
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
-        Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
-        Registrant r = new Registrant(h, what, obj);
-        psRestrictEnabledRegistrants.add(r);
-
-        if (rs.isPsRestricted()) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForPsRestrictedEnabled(Handler h) {
-        psRestrictEnabledRegistrants.remove(h);
-    }
-
-    /**
-     * Registration point for transition out of packet service restricted zone.
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
-        Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
-        Registrant r = new Registrant(h, what, obj);
-        psRestrictDisabledRegistrants.add(r);
-
-        if (rs.isPsRestricted()) {
-            r.notifyRegistrant();
-        }
-    }
-
-    void unregisterForPsRestrictedDisabled(Handler h) {
-        psRestrictDisabledRegistrants.remove(h);
-    }
-
     public void handleMessage (Message msg) {
         AsyncResult ar;
         int[] ints;
@@ -567,33 +470,21 @@
             && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
             cm.setRadioPower(true, null);
         } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
-            DataConnectionTracker dcTracker = phone.mDataConnection;
-            if (! dcTracker.isDataConnectionAsDesired()) {
-                EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
-                        dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0);
-            }
             // If it's on and available and we want it off gracefully
             powerOffRadioSafely();
         } // Otherwise, we're in the desired state
     }
 
     @Override
-    protected void powerOffRadioSafely() {
-        // clean data connection
+    public void powerOffRadioSafely() {
+        // Cleanup all connections
         DataConnectionTracker dcTracker = phone.mDataConnection;
-        Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
-        msg.arg1 = 1; // tearDown is true
-        msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
+        Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_ALL_CONNECTIONS);
         dcTracker.sendMessage(msg);
 
         // poll data state up to 15 times, with a 100ms delay
         // totaling 1.5 sec. Normal data disable action will finish in 100ms.
         for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
-            if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
-                    && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
-                Log.d(LOG_TAG, "Data shutdown complete.");
-                break;
-            }
             SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
         }
 
@@ -988,7 +879,7 @@
         }
 
         if (hasRegistered) {
-            networkAttachedRegistrants.notifyRegistrants();
+            mNetworkAttachedRegistrants.notifyRegistrants();
         }
 
         if (hasChanged) {
@@ -1065,23 +956,23 @@
         }
 
         if (hasGprsAttached) {
-            gprsAttachedRegistrants.notifyRegistrants();
+            mAttachedRegistrants.notifyRegistrants();
         }
 
         if (hasGprsDetached) {
-            gprsDetachedRegistrants.notifyRegistrants();
+            mDetachedRegistrants.notifyRegistrants();
         }
 
         if (hasNetworkTypeChanged) {
-            phone.notifyDataConnection();
+            phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED, Phone.APN_TYPE_ALL);
         }
 
         if (hasRoamingOn) {
-            roamingOnRegistrants.notifyRegistrants();
+            mRoamingOnRegistrants.notifyRegistrants();
         }
 
         if (hasRoamingOff) {
-            roamingOffRegistrants.notifyRegistrants();
+            mRoamingOffRegistrants.notifyRegistrants();
         }
 
         if (hasLocationChanged) {
@@ -1229,7 +1120,7 @@
         Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
         RestrictedState newRs = new RestrictedState();
 
-        Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ rs);
+        Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ mRestrictedState);
 
         if (ar.exception == null) {
             int[] ints = (int[])ar.result;
@@ -1249,11 +1140,11 @@
 
             Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
 
-            if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
-                psRestrictEnabledRegistrants.notifyRegistrants();
+            if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
+                mPsRestrictEnabledRegistrants.notifyRegistrants();
                 setNotification(PS_ENABLED);
-            } else if (rs.isPsRestricted() && !newRs.isPsRestricted()) {
-                psRestrictDisabledRegistrants.notifyRegistrants();
+            } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
+                mPsRestrictDisabledRegistrants.notifyRegistrants();
                 setNotification(PS_DISABLED);
             }
 
@@ -1262,7 +1153,7 @@
              * there are 4 x 4 combinations in current and new restricted states
              * and we only need to notify when state is changed.
              */
-            if (rs.isCsRestricted()) {
+            if (mRestrictedState.isCsRestricted()) {
                 if (!newRs.isCsRestricted()) {
                     // remove all restriction
                     setNotification(CS_DISABLED);
@@ -1273,7 +1164,8 @@
                     // remove emergency restriction
                     setNotification(CS_NORMAL_ENABLED);
                 }
-            } else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
+            } else if (mRestrictedState.isCsEmergencyRestricted() &&
+                    !mRestrictedState.isCsNormalRestricted()) {
                 if (!newRs.isCsRestricted()) {
                     // remove all restriction
                     setNotification(CS_DISABLED);
@@ -1284,7 +1176,8 @@
                     // remove emergency restriction and enable normal restriction
                     setNotification(CS_NORMAL_ENABLED);
                 }
-            } else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
+            } else if (!mRestrictedState.isCsEmergencyRestricted() &&
+                    mRestrictedState.isCsNormalRestricted()) {
                 if (!newRs.isCsRestricted()) {
                     // remove all restriction
                     setNotification(CS_DISABLED);
@@ -1308,9 +1201,9 @@
                 }
             }
 
-            rs = newRs;
+            mRestrictedState = newRs;
         }
-        Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
+        Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ mRestrictedState);
     }
 
     /** code is registration state 0-5 from TS 27.007 7.2 */
@@ -1401,11 +1294,15 @@
         return gprsState;
     }
 
+    public int getCurrentDataConnectionState() {
+        return gprsState;
+    }
+
     /**
      * @return true if phone is camping on a technology (eg UMTS)
      * that could support voice and data simultaneously.
      */
-    boolean isConcurrentVoiceAndData() {
+    public boolean isConcurrentVoiceAndDataAllowed() {
         return (networkType >= DATA_ACCESS_UMTS);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 3b133da..11ce83e 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -35,6 +35,7 @@
 import com.android.internal.telephony.IccVmFixedException;
 import com.android.internal.telephony.IccVmNotSupportedException;
 import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.PhoneBase;
 
 import java.util.ArrayList;
 
@@ -165,7 +166,7 @@
 
     // ***** Constructor
 
-    SIMRecords(GSMPhone p) {
+    public SIMRecords(PhoneBase p) {
         super(p);
 
         adnCache = new AdnRecordCache(phone);
@@ -364,7 +365,7 @@
 
         countVoiceMessages = countWaiting;
 
-        ((GSMPhone) phone).notifyMessageWaitingIndicator();
+        phone.notifyMessageWaitingIndicator();
 
         try {
             if (efMWIS != null) {
@@ -413,7 +414,7 @@
 
         callForwardingEnabled = enable;
 
-        ((GSMPhone) phone).notifyCallForwardingIndicator();
+        phone.notifyCallForwardingIndicator();
 
         try {
             if (mEfCfis != null) {
@@ -470,7 +471,7 @@
     /** Returns the 5 or 6 digit MCC/MNC of the operator that
      *  provided the SIM card. Returns null of SIM is not yet ready
      */
-    String getSIMOperatorNumeric() {
+    public String getSIMOperatorNumeric() {
         if (imsi == null || mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
             return null;
         }
@@ -547,7 +548,7 @@
                     // finally have both the imsi and the mncLength and can parse the imsi properly
                     MccTable.updateMccMncConfiguration(phone, imsi.substring(0, 3 + mncLength));
                 }
-                ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+                phone.mSimCard.broadcastIccStateChangedIntent(
                         SimCard.INTENT_VALUE_ICC_IMSI, null);
             break;
 
@@ -702,7 +703,7 @@
                     countVoiceMessages = -1;
                 }
 
-                ((GSMPhone) phone).notifyMessageWaitingIndicator();
+                phone.notifyMessageWaitingIndicator();
             break;
 
             case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
@@ -731,7 +732,7 @@
                         countVoiceMessages = 0;
                     }
 
-                    ((GSMPhone) phone).notifyMessageWaitingIndicator();
+                    phone.notifyMessageWaitingIndicator();
                 }
             break;
 
@@ -842,7 +843,7 @@
                     callForwardingEnabled =
                         ((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
 
-                    ((GSMPhone) phone).notifyCallForwardingIndicator();
+                    phone.notifyCallForwardingIndicator();
                 }
                 break;
 
@@ -1042,7 +1043,7 @@
                 // Refer TS 51.011 Section 10.3.46 for the content description
                 callForwardingEnabled = ((data[1] & 0x01) != 0);
 
-                ((GSMPhone) phone).notifyCallForwardingIndicator();
+                phone.notifyCallForwardingIndicator();
                 break;
 
             case EVENT_GET_CSP_CPHS_DONE:
@@ -1152,7 +1153,7 @@
             System.arraycopy(ba, 1, pdu, 0, n - 1);
             SmsMessage message = SmsMessage.createFromPdu(pdu);
 
-            ((GSMPhone) phone).mSMS.dispatchMessage(message);
+            phone.mSMS.dispatchMessage(message);
         }
     }
 
@@ -1178,7 +1179,7 @@
                 System.arraycopy(ba, 1, pdu, 0, n - 1);
                 SmsMessage message = SmsMessage.createFromPdu(pdu);
 
-                ((GSMPhone) phone).mSMS.dispatchMessage(message);
+                phone.mSMS.dispatchMessage(message);
 
                 // 3GPP TS 51.011 v5.0.0 (20011-12)  10.5.3
                 // 1 == "received by MS from network; message read"
@@ -1228,7 +1229,7 @@
 
         recordsLoadedRegistrants.notifyRegistrants(
             new AsyncResult(null, null, null));
-        ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+        phone.mSimCard.broadcastIccStateChangedIntent(
                 SimCard.INTENT_VALUE_ICC_LOADED, null);
     }
 
@@ -1249,11 +1250,11 @@
         }
     }
 
-    private void onSimReady() {
+    public void onSimReady() {
         /* broadcast intent SIM_READY here so that we can make sure
           READY is sent before IMSI ready
         */
-        ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+        phone.mSimCard.broadcastIccStateChangedIntent(
                 SimCard.INTENT_VALUE_ICC_READY, null);
 
         fetchSimRecords();
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
index 835cb29..781746c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -19,6 +19,9 @@
 import android.util.Log;
 
 import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.TelephonyProperties;
+import android.os.SystemProperties;
 
 /**
  * {@hide}
@@ -34,6 +37,21 @@
         updateStateProperty();
     }
 
+    /**
+    * We have the Sim card for LTE on CDMA phone
+    */
+    public SimCard(PhoneBase phone, String logTag, Boolean dbg) {
+        super(phone, logTag, dbg);
+        mPhone.mCM.registerForSIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
+        mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        mPhone.mCM.registerForSIMReady(mHandler, EVENT_ICC_READY, null);
+        updateStateProperty();
+
+        if(SystemProperties.getBoolean(TelephonyProperties.PROPERTY_NETWORK_LTE_ON_CDMA, false)) {
+            mPhone.mCM.registerForNVReady(mHandler, EVENT_ICC_READY, null);
+        }
+    }
+
     @Override
     public void dispose() {
         //Unregister for all events