Merge change 23908 into eclair

* changes:
  Add another testcase for moto to reproduce bug #2099685 to the stagefright commandline app.
diff --git a/api/current.xml b/api/current.xml
index b052a61..7bb99e4 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -17373,6 +17373,21 @@
  visibility="public"
 >
 </method>
+<method name="getRunningServiceControlPanel"
+ return="android.app.PendingIntent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="service" type="android.content.ComponentName">
+</parameter>
+<exception name="SecurityException" type="java.lang.SecurityException">
+</exception>
+</method>
 <method name="getRunningServices"
  return="java.util.List&lt;android.app.ActivityManager.RunningServiceInfo&gt;"
  abstract="false"
@@ -17942,6 +17957,39 @@
  visibility="public"
 >
 </field>
+<field name="REASON_PROVIDER_IN_USE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REASON_SERVICE_IN_USE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REASON_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="importance"
  type="int"
  transient="false"
@@ -17952,6 +18000,36 @@
  visibility="public"
 >
 </field>
+<field name="importanceReasonCode"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="importanceReasonComponent"
+ type="android.content.ComponentName"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="importanceReasonPid"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="lru"
  type="int"
  transient="false"
@@ -18125,6 +18203,26 @@
  visibility="public"
 >
 </field>
+<field name="clientLabel"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="clientPackage"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="crashCount"
  type="int"
  transient="false"
@@ -112103,6 +112201,17 @@
  visibility="public"
 >
 </constructor>
+<field name="ACTION_ACCESSIBILITY_SETTINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.settings.ACCESSIBILITY_SETTINGS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_AIRPLANE_MODE_SETTINGS"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ad06fa9..af73112 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -366,6 +366,19 @@
          */
         public int flags;
         
+        /**
+         * For special services that are bound to by system code, this is
+         * the package that holds the binding.
+         */
+        public String clientPackage;
+        
+        /**
+         * For special services that are bound to by system code, this is
+         * a string resource providing a user-visible label for who the
+         * client is.
+         */
+        public int clientLabel;
+        
         public RunningServiceInfo() {
         }
 
@@ -386,6 +399,8 @@
             dest.writeLong(lastActivityTime);
             dest.writeLong(restarting);
             dest.writeInt(this.flags);
+            dest.writeString(clientPackage);
+            dest.writeInt(clientLabel);
         }
 
         public void readFromParcel(Parcel source) {
@@ -401,6 +416,8 @@
             lastActivityTime = source.readLong();
             restarting = source.readLong();
             flags = source.readInt();
+            clientPackage = source.readString();
+            clientLabel = source.readInt();
         }
         
         public static final Creator<RunningServiceInfo> CREATOR = new Creator<RunningServiceInfo>() {
@@ -439,6 +456,22 @@
     }
     
     /**
+     * Returns a PendingIntent you can start to show a control panel for the
+     * given running service.  If the service does not have a control panel,
+     * null is returned.
+     */
+    public PendingIntent getRunningServiceControlPanel(ComponentName service)
+            throws SecurityException {
+        try {
+            return ActivityManagerNative.getDefault()
+                    .getRunningServiceControlPanel(service);
+        } catch (RemoteException e) {
+            // System dead, we will be dead too soon!
+            return null;
+        }
+    }
+    
+    /**
      * Information you can retrieve about the available memory through
      * {@link ActivityManager#getMemoryInfo}.
      */
@@ -704,8 +737,51 @@
          */
         public int lru;
         
+        /**
+         * Constant for {@link #importanceReasonCode}: nothing special has
+         * been specified for the reason for this level.
+         */
+        public static final int REASON_UNKNOWN = 0;
+        
+        /**
+         * Constant for {@link #importanceReasonCode}: one of the application's
+         * content providers is being used by another process.  The pid of
+         * the client process is in {@link #importanceReasonPid} and the
+         * target provider in this process is in
+         * {@link #importanceReasonComponent}.
+         */
+        public static final int REASON_PROVIDER_IN_USE = 1;
+        
+        /**
+         * Constant for {@link #importanceReasonCode}: one of the application's
+         * content providers is being used by another process.  The pid of
+         * the client process is in {@link #importanceReasonPid} and the
+         * target provider in this process is in
+         * {@link #importanceReasonComponent}.
+         */
+        public static final int REASON_SERVICE_IN_USE = 2;
+        
+        /**
+         * The reason for {@link #importance}, if any.
+         */
+        public int importanceReasonCode;
+        
+        /**
+         * For the specified values of {@link #importanceReasonCode}, this
+         * is the process ID of the other process that is a client of this
+         * process.  This will be 0 if no other process is using this one.
+         */
+        public int importanceReasonPid;
+        
+        /**
+         * For the specified values of {@link #importanceReasonCode}, this
+         * is the name of the component that is being used in this process.
+         */
+        public ComponentName importanceReasonComponent;
+        
         public RunningAppProcessInfo() {
             importance = IMPORTANCE_FOREGROUND;
+            importanceReasonCode = REASON_UNKNOWN;
         }
         
         public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
@@ -724,6 +800,9 @@
             dest.writeStringArray(pkgList);
             dest.writeInt(importance);
             dest.writeInt(lru);
+            dest.writeInt(importanceReasonCode);
+            dest.writeInt(importanceReasonPid);
+            ComponentName.writeToParcel(importanceReasonComponent, dest);
         }
 
         public void readFromParcel(Parcel source) {
@@ -732,6 +811,9 @@
             pkgList = source.readStringArray();
             importance = source.readInt();
             lru = source.readInt();
+            importanceReasonCode = source.readInt();
+            importanceReasonPid = source.readInt();
+            importanceReasonComponent = ComponentName.readFromParcel(source);
         }
 
         public static final Creator<RunningAppProcessInfo> CREATOR = 
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 213f26e..4ed152e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -510,6 +510,15 @@
             return true;
         }
         
+        case GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            ComponentName comp = ComponentName.CREATOR.createFromParcel(data);
+            PendingIntent pi = getRunningServiceControlPanel(comp);
+            reply.writeNoException();
+            PendingIntent.writePendingIntentOrNullToParcel(pi, reply);
+            return true;
+        }
+
         case START_SERVICE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder b = data.readStrongBinder();
@@ -1634,6 +1643,21 @@
         reply.recycle();
     }
     
+    public PendingIntent getRunningServiceControlPanel(ComponentName service)
+            throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        service.writeToParcel(data, 0);
+        mRemote.transact(GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION, data, reply, 0);
+        reply.readException();
+        PendingIntent res = PendingIntent.readPendingIntentOrNullFromParcel(reply);
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+    
     public ComponentName startService(IApplicationThread caller, Intent service,
             String resolvedType) throws RemoteException
     {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index a7bef54..a937c11 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -126,13 +126,15 @@
     public void finishOtherInstances(IBinder token, ComponentName className) throws RemoteException;
     /* oneway */
     public void reportThumbnail(IBinder token,
-                                Bitmap thumbnail, CharSequence description) throws RemoteException;
+            Bitmap thumbnail, CharSequence description) throws RemoteException;
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
-                                                    String name) throws RemoteException;
+            String name) throws RemoteException;
     public void removeContentProvider(IApplicationThread caller,
-        String name) throws RemoteException;
+            String name) throws RemoteException;
     public void publishContentProviders(IApplicationThread caller,
-                                        List<ContentProviderHolder> providers) throws RemoteException;
+            List<ContentProviderHolder> providers) throws RemoteException;
+    public PendingIntent getRunningServiceControlPanel(ComponentName service)
+            throws RemoteException;
     public ComponentName startService(IApplicationThread caller, Intent service,
             String resolvedType) throws RemoteException;
     public int stopService(IApplicationThread caller, Intent service,
@@ -367,7 +369,7 @@
     int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
     int SET_PERSISTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
     int FINISH_SUB_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
-    
+    int GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
     int START_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
     int STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
     int BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 87a8f39..1d1161e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2044,6 +2044,24 @@
     public static final String EXTRA_CHANGED_COMPONENT_NAME =
             "android.intent.extra.changed_component_name";
 
+    /**
+     * @hide
+     * Magic extra system code can use when binding, to give a label for
+     * who it is that has bound to a service.  This is an integer giving
+     * a framework string resource that can be displayed to the user.
+     */
+    public static final String EXTRA_CLIENT_LABEL =
+            "android.intent.extra.client_label";
+
+    /**
+     * @hide
+     * Magic extra system code can use when binding, to give a PendingIntent object
+     * that can be launched for the user to disable the system's use of this
+     * service.
+     */
+    public static final String EXTRA_CLIENT_INTENT =
+            "android.intent.extra.client_intent";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 5ffe962..6d27bc7 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1064,6 +1064,10 @@
             Intent intent = new Intent();
             intent.setAction("android.content.SyncAdapter");
             intent.setComponent(info.componentName);
+            intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+                    com.android.internal.R.string.sync_binding_label);
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                    mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
             return mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
         }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 125ed0b..64e47eb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -119,6 +119,20 @@
             "android.settings.AIRPLANE_MODE_SETTINGS";
 
     /**
+     * Activity Action: Show settings for accessibility modules.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_ACCESSIBILITY_SETTINGS =
+            "android.settings.ACCESSIBILITY_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow configuration of security and
      * location privacy.
      * <p>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 70c9385..3333915 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1943,25 +1943,34 @@
     <string-array translatable="false" name="carrier_properties">
     </string-array>
 
-     <!-- Title for the selected state of a CompoundButton. -->
-     <string name="accessibility_compound_button_selected">checked</string>
+    <!-- Title for the selected state of a CompoundButton. -->
+    <string name="accessibility_compound_button_selected">checked</string>
 
-     <!-- Title for the unselected state of a CompoundButton. -->
-     <string name="accessibility_compound_button_unselected">not checked</string>
+    <!-- Title for the unselected state of a CompoundButton. -->
+    <string name="accessibility_compound_button_unselected">not checked</string>
 
-     <string name="grant_credentials_permission_message_desc">The
-     listed applications are requesting permission to access the login credentials for account <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g> from
-     <xliff:g id="application" example="Google Apps">%2$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
-     again.</string>
+    <string name="grant_credentials_permission_message_desc">The
+    listed applications are requesting permission to access the login credentials for account <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g> from
+    <xliff:g id="application" example="Google Apps">%2$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
+    again.</string>
 
-     <string name="grant_credentials_permission_message_with_authtokenlabel_desc">The
-     listed applications are requesting permission to access the <xliff:g id="type" example="Contacts">%1$s</xliff:g> login credentials for account <xliff:g id="account" example="foo@gmail.com">%2$s</xliff:g> from
-     <xliff:g id="application" example="Google Apps">%3$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
-     again.</string>
+    <string name="grant_credentials_permission_message_with_authtokenlabel_desc">The
+    listed applications are requesting permission to access the <xliff:g id="type" example="Contacts">%1$s</xliff:g> login credentials for account <xliff:g id="account" example="foo@gmail.com">%2$s</xliff:g> from
+    <xliff:g id="application" example="Google Apps">%3$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
+    again.</string>
 
-     <string name="allow">Allow</string>
-     <string name="deny">Deny</string>
-     <string name="permission_request_notification_title">Permission Requested</string>
-     <string name="permission_request_notification_subtitle">for account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g></string>
+    <string name="allow">Allow</string>
+    <string name="deny">Deny</string>
+    <string name="permission_request_notification_title">Permission Requested</string>
+    <string name="permission_request_notification_subtitle">for account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g></string>
 
+    <!-- Label to show for a service that is running because it is an input method. -->
+    <string name="input_method_binding_label">Input method</string>
+    <!-- Label to show for a service that is running because it is a sync adapter. -->
+    <string name="sync_binding_label">Sync</string>
+    <!-- Label to show for a service that is running because it is an accessibility module. -->
+    <string name="accessibility_binding_label">Accessibility</string>
+    <!-- Label to show for a service that is running because it is a wallpaper. -->
+    <string name="wallpaper_binding_label">Wallpaper</string>
+    
 </resources>
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 536f71c..e6cb395 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -110,9 +110,12 @@
     }
 
     public void data(Object o) {
-        mRS.nAllocationDataFromObject(mID, mType, o);
+        mRS.nAllocationSubDataFromObject(mID, mType, 0, o);
     }
 
+    public void subData(int offset, Object o) {
+        mRS.nAllocationSubDataFromObject(mID, mType, offset, o);
+    }
 
     public class Adapter1D extends BaseObj {
         Adapter1D(int id, RenderScript rs) {
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 0ca112c..0b7e667 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -244,8 +244,8 @@
         }
 
         public Builder addFloatXY(String prefix) {
-            add(DataType.FLOAT, DataKind.X, false, 32, prefix + "X");
-            add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "Y");
+            add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x");
+            add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y");
             return this;
         }
 
@@ -257,9 +257,9 @@
         }
 
         public Builder addFloatXYZ(String prefix) {
-            add(DataType.FLOAT, DataKind.X, false, 32, prefix + "X");
-            add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "Y");
-            add(DataType.FLOAT, DataKind.Z, false, 32, prefix + "Z");
+            add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x");
+            add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y");
+            add(DataType.FLOAT, DataKind.Z, false, 32, prefix + "z");
             return this;
         }
 
@@ -270,8 +270,8 @@
         }
 
         public Builder addFloatST(String prefix) {
-            add(DataType.FLOAT, DataKind.S, false, 32, prefix + "S");
-            add(DataType.FLOAT, DataKind.T, false, 32, prefix + "T");
+            add(DataType.FLOAT, DataKind.S, false, 32, prefix + "s");
+            add(DataType.FLOAT, DataKind.T, false, 32, prefix + "t");
             return this;
         }
 
@@ -283,9 +283,9 @@
         }
 
         public Builder addFloatNorm(String prefix) {
-            add(DataType.FLOAT, DataKind.NX, false, 32, prefix + "NX");
-            add(DataType.FLOAT, DataKind.NY, false, 32, prefix + "NY");
-            add(DataType.FLOAT, DataKind.NZ, false, 32, prefix + "NZ");
+            add(DataType.FLOAT, DataKind.NX, false, 32, prefix + "nx");
+            add(DataType.FLOAT, DataKind.NY, false, 32, prefix + "ny");
+            add(DataType.FLOAT, DataKind.NZ, false, 32, prefix + "nz");
             return this;
         }
 
@@ -294,8 +294,8 @@
             return this;
         }
 
-        public Builder addFloatPointSize(String name) {
-            add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, name);
+        public Builder addFloatPointSize(String prefix) {
+            add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, prefix + "pointSize");
             return this;
         }
 
@@ -307,9 +307,9 @@
         }
 
         public Builder addFloatRGB(String prefix) {
-            add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "R");
-            add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "G");
-            add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "B");
+            add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r");
+            add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g");
+            add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b");
             return this;
         }
 
@@ -322,10 +322,10 @@
         }
 
         public Builder addFloatRGBA(String prefix) {
-            add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "R");
-            add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "G");
-            add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "B");
-            add(DataType.FLOAT, DataKind.ALPHA, false, 32, prefix + "A");
+            add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r");
+            add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g");
+            add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b");
+            add(DataType.FLOAT, DataKind.ALPHA, false, 32, prefix + "a");
             return this;
         }
 
@@ -338,10 +338,10 @@
         }
 
         public Builder addUNorm8RGBA(String prefix) {
-            add(DataType.UNSIGNED, DataKind.RED, true, 8, prefix + "R");
-            add(DataType.UNSIGNED, DataKind.GREEN, true, 8, prefix + "G");
-            add(DataType.UNSIGNED, DataKind.BLUE, true, 8, prefix + "B");
-            add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, prefix + "A");
+            add(DataType.UNSIGNED, DataKind.RED, true, 8, prefix + "r");
+            add(DataType.UNSIGNED, DataKind.GREEN, true, 8, prefix + "g");
+            add(DataType.UNSIGNED, DataKind.BLUE, true, 8, prefix + "b");
+            add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, prefix + "a");
             return this;
         }
 
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 0f188f6..bd345e5 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -106,7 +106,7 @@
     native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d, int sizeBytes);
     native void nAllocationRead(int id, int[] d);
     native void nAllocationRead(int id, float[] d);
-    native void nAllocationDataFromObject(int id, Type t, Object o);
+    native void nAllocationSubDataFromObject(int id, Type t, int offset, Object o);
 
     native void nTriangleMeshBegin(int vertex, int index);
     native void nTriangleMeshAddVertex_XY (float x, float y);
diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java
index e66fb8a..5d87654 100644
--- a/graphics/java/android/renderscript/SimpleMesh.java
+++ b/graphics/java/android/renderscript/SimpleMesh.java
@@ -50,6 +50,13 @@
         return Allocation.createTyped(mRS, mIndexType);
     }
 
+    public Type getVertexType(int slot) {
+        return mVertexTypes[slot];
+    }
+
+    public Type getIndexType() {
+        return mIndexType;
+    }
 
     public static class Builder {
         RenderScript mRS;
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 558146d..62c3914 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -543,7 +543,7 @@
 
 //{"nAllocationDataFromObject",      "(ILandroid/renderscript/Type;Ljava/lang/Object;)V",   (void*)nAllocationDataFromObject },
 static void
-nAllocationDataFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jobject _o)
+nAllocationSubDataFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jint offset, jobject _o)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
     LOG_API("nAllocationDataFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
@@ -556,7 +556,7 @@
         const TypeFieldCache *tfc = &tc->fields[ct];
         buf = tfc->ptr(_env, _o, tfc->field, buf);
     }
-    rsAllocationData(con, (RsAllocation)alloc, bufAlloc, tc->size);
+    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, 1, bufAlloc, tc->size);
     const uint32_t * tmp = (const uint32_t *)bufAlloc;
     free(bufAlloc);
 }
@@ -1282,7 +1282,7 @@
 {"nAllocationSubData2D",           "(IIIII[FI)V",                          (void*)nAllocationSubData2D_f },
 {"nAllocationRead",                "(I[I)V",                               (void*)nAllocationRead_i },
 {"nAllocationRead",                "(I[F)V",                               (void*)nAllocationRead_f },
-{"nAllocationDataFromObject",      "(ILandroid/renderscript/Type;Ljava/lang/Object;)V",   (void*)nAllocationDataFromObject },
+{"nAllocationSubDataFromObject",   "(ILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubDataFromObject },
 
 {"nTriangleMeshBegin",             "(II)V",                                (void*)nTriangleMeshBegin },
 {"nTriangleMeshAddVertex_XY",      "(FF)V",                                (void*)nTriangleMeshAddVertex_XY },
diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c
index f348a62..c09f43c 100644
--- a/libs/rs/java/Fall/res/raw/fall.c
+++ b/libs/rs/java/Fall/res/raw/fall.c
@@ -52,8 +52,8 @@
 }
 
 void dropWithStrength(int x, int y, int r, int s) {
-    int width = State_meshWidth;
-    int height = State_meshHeight;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
 
     if (x < r) x = r;
     if (y < r) y = r;
@@ -62,8 +62,8 @@
 
     x = width - x;
 
-    int rippleMapSize = State_rippleMapSize;
-    int index = State_rippleIndex;
+    int rippleMapSize = State->rippleMapSize;
+    int index = State->rippleIndex;
     int origin = offset(0, 0, width);
 
     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
@@ -94,10 +94,10 @@
 }
 
 void updateRipples() {
-    int rippleMapSize = State_rippleMapSize;
-    int width = State_meshWidth;
-    int height = State_meshHeight;
-    int index = State_rippleIndex;
+    int rippleMapSize = State->rippleMapSize;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+    int index = State->rippleIndex;
     int origin = offset(0, 0, width);
 
     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
@@ -139,9 +139,9 @@
 
 void generateRipples() {
     int rippleMapSize = loadI32(RSID_STATE, OFFSETOF_WorldState_rippleMapSize);
-    int width = State_meshWidth;
-    int height = State_meshHeight;
-    int index = State_rippleIndex;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+    int index = State->rippleIndex;
     int origin = offset(0, 0, width);
 
     int b = width + 2;
@@ -180,7 +180,7 @@
 
             // Update Z coordinate of the vertex
             vertices[index + 7] = dy * fy;
-            
+
             w -= 1;
             current += 1;
             wave = nextWave;
@@ -210,7 +210,7 @@
             float v2x = vertices[o1 + 5];
             float v2y = vertices[o1 + 6];
             float v2z = vertices[o1 + 7];
-            
+
             // V3
             float v3x = vertices[ow + 5];
             float v3y = vertices[ow + 6];
@@ -236,7 +236,7 @@
             n3x *= len;
             n3y *= len;
             n3z *= len;
-            
+
             // V2
             v2x = vertices[ow1 + 5];
             v2y = vertices[ow1 + 6];
@@ -266,7 +266,7 @@
             vertices[o + 0] = n3x;
             vertices[o + 1] = n3y;
             vertices[o + 2] = -n3z;
-            
+
             // reset Z
             //vertices[(yOffset + x) << 3 + 7] = 0.0f;
         }
@@ -322,7 +322,7 @@
     float z2 = 0.0f;
     float z3 = 0.0f;
     float z4 = 0.0f;
-    
+
     float a = leafStruct[LEAF_STRUCT_ALTITUDE];
     float s = leafStruct[LEAF_STRUCT_SCALE];
     float r = leafStruct[LEAF_STRUCT_ANGLE];
@@ -384,7 +384,7 @@
         LEAF_SIZE * s + y < -glHeight / 2.0f) {
 
         int sprite = randf(LEAVES_TEXTURES_COUNT);
-        leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);   
+        leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);
         leafStruct[LEAF_STRUCT_Y] = glHeight / 2.0f + LEAF_SIZE * 2 * randf(1.0f);
         leafStruct[LEAF_STRUCT_SCALE] = randf2(0.4f, 0.5f);
         leafStruct[LEAF_STRUCT_SPIN] = degf(randf2(-0.02f, 0.02f)) / 4.0f;
@@ -401,20 +401,20 @@
     bindProgramVertex(NAMED_PVSky);
     bindTexture(NAMED_PFBackground, 0, NAMED_TLeaves);
 
-    int leavesCount = State_leavesCount;
+    int leavesCount = State->leavesCount;
     int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
-    int width = State_meshWidth;
-    int height = State_meshHeight;    
-    float glWidth = State_glWidth;
-    float glHeight = State_glHeight;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+    float glWidth = State->glWidth;
+    float glHeight = State->glHeight;
 
-    float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);    
+    float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
 
     int i = 0;
     for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
         drawLeaf(i, vertices, width, height, glWidth, glHeight);
     }
-    
+
     float matrix[16];
     matrixLoadIdentity(matrix);
     vpLoadModelMatrix(matrix);
@@ -433,8 +433,8 @@
     bindProgramFragmentStore(NAMED_PFSLeaf);
     bindTexture(NAMED_PFSky, 0, NAMED_TSky);
 
-    float x = State_skyOffsetX + State_skySpeedX;
-    float y = State_skyOffsetY + State_skySpeedY;
+    float x = State->skyOffsetX + State->skySpeedX;
+    float y = State->skyOffsetY + State->skySpeedY;
 
     if (x > 1.0f) x = 0.0f;
     if (x < -1.0f) x = 0.0f;
@@ -467,8 +467,8 @@
 }
 
 void drawNormals() {
-    int width = State_meshWidth;
-    int height = State_meshHeight;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
 
     float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
 
@@ -496,12 +496,10 @@
 }
 
 int main(int index) {
-    int dropX = Drop_dropX;
-    if (dropX != -1) {
-        int dropY = Drop_dropY;
-        drop(dropX, dropY, DROP_RADIUS);
-        storeI32(RSID_DROP, OFFSETOF_DropState_dropX, -1);
-        storeI32(RSID_DROP, OFFSETOF_DropState_dropY, -1);
+    if (Drop->dropX != -1) {
+        drop(Drop->dropX, Drop->dropY, DROP_RADIUS);
+        Drop->dropX = -1;
+        Drop->dropY = -1;
     }
 
     updateRipples();
diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c
index 8f3d930..8fbfee1 100644
--- a/libs/rs/java/Film/res/raw/filmstrip.c
+++ b/libs/rs/java/Film/res/raw/filmstrip.c
@@ -5,10 +5,6 @@
 #pragma stateFragment(PFBackground)
 #pragma stateFragmentStore(PSBackground)
 
-#define POS_TRANSLATE 0
-#define POS_ROTATE 1
-#define POS_FOCUS 2
-
 #define STATE_TRIANGLE_OFFSET_COUNT 0
 #define STATE_LAST_FOCUS 1
 
@@ -18,12 +14,14 @@
 // bank1: (r) The position information
 // bank2: (rw) The temporary texture state
 
+int lastFocus;
+
 int main(int index)
 {
     float mat1[16];
 
-    float trans = Pos_translate;
-    float rot = Pos_rotate;
+    float trans = Pos->translate;
+    float rot = Pos->rotate;
 
     matrixLoadScale(mat1, 2.f, 2.f, 2.f);
     matrixTranslate(mat1, 0.f, 0.f, trans);
@@ -39,7 +37,7 @@
     bindProgramFragment(NAMED_PFImages);
     bindProgramVertex(NAMED_PVImages);
 
-    float focusPos = Pos_focus;
+    float focusPos = Pos->focus;
     int focusID = 0;
     int lastFocusID = loadI32(2, STATE_LAST_FOCUS);
     int imgCount = 13;
@@ -63,9 +61,9 @@
         }
     }
     */
-    storeI32(2, STATE_LAST_FOCUS, focusID);
+    lastFocus = focusID;
 
-    int triangleOffsetsCount = Pos_triangleOffsetCount;
+    int triangleOffsetsCount = Pos->triangleOffsetCount;
 
     int imgId = 0;
     for (imgId=1; imgId <= imgCount; imgId++) {
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 99f4048..36516c2 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -4,27 +4,32 @@
 #pragma stateFragment(default)
 #pragma stateFragmentStore(default)
 
-struct PartStruct {float dx; float dy; float x; float y; int c;};
 int newPart = 0;
 
 int main(int launchID) {
     int ct;
-    int count = Control_count - 1;
-    int rate = Control_rate;
+    int count = Control->count;
+    int rate = Control->rate;
     float height = getHeight();
-    struct PartStruct * p = (struct PartStruct *)loadArrayF(1, 0);
+    struct point_s * p = (struct point_s *)point;
 
     if (rate) {
         float rMax = ((float)rate) * 0.005f;
-        int x = Control_x;
-        int y = Control_y;
-        int c = colorFloatRGBAtoUNorm8(Control_r, Control_g, Control_b, 0.99f);
+        int x = Control->x;
+        int y = Control->y;
+        char r = Control->r * 255.f;
+        char g = Control->g * 255.f;
+        char b = Control->b * 255.f;
+        char a = 0xf0;
 
         while (rate--) {
             vec2Rand((float *)(p + newPart), rMax);
             p[newPart].x = x;
             p[newPart].y = y;
-            p[newPart].c = c;
+            p[newPart].r = r;
+            p[newPart].g = g;
+            p[newPart].b = b;
+            p[newPart].a = a;
             newPart++;
             if (newPart >= count) {
                 newPart = 0;
@@ -45,6 +50,6 @@
     }
 
     uploadToBufferObject(NAMED_PartBuffer);
-    drawSimpleMeshRange(NAMED_PartMesh, 0, count);
+    drawSimpleMesh(NAMED_PartMesh);
     return 1;
 }
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index 6d400c5..f4f9b0c 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -79,10 +79,10 @@
         mIntAlloc.data(mSD);
 
         Element.Builder eb = new Element.Builder(mRS);
-        eb.addFloat(Element.DataKind.USER); //dx
-        eb.addFloat(Element.DataKind.USER); //dy
-        eb.addFloatXY();
-        eb.addUNorm8RGBA();
+        eb.addFloat(Element.DataKind.USER, "dx");
+        eb.addFloat(Element.DataKind.USER, "dy");
+        eb.addFloatXY("");
+        eb.addUNorm8RGBA("");
         Element primElement = eb.create();
 
 
@@ -102,6 +102,7 @@
         sb.setScript(mRes, R.raw.fountain);
         sb.setRoot(true);
         sb.setType(mSDType, "Control", 0);
+        sb.setType(mSM.getVertexType(0), "point", 1);
         Script script = sb.create();
         script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index c28bd02..c132915 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -116,6 +116,7 @@
     //glEnable(GL_LIGHT0);
     glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    glEnable(GL_POINT_SMOOTH);
 
     glClearColor(mRootScript->mEnviroment.mClearColor[0],
                  mRootScript->mEnviroment.mClearColor[1],
@@ -153,10 +154,18 @@
 void Context::timerInit()
 {
     mTimeLast = getTime();
+    mTimeFrame = mTimeLast;
+    mTimeLastFrame = mTimeLast;
     mTimerActive = RS_TIMER_INTERNAL;
     timerReset();
 }
 
+void Context::timerFrame()
+{
+    mTimeLastFrame = mTimeFrame;
+    mTimeFrame = getTime();
+}
+
 void Context::timerSet(Timers tm)
 {
     uint64_t last = mTimeLast;
@@ -171,8 +180,10 @@
     for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
         total += mTimers[ct];
     }
+    uint64_t frame = mTimeFrame - mTimeLastFrame;
 
-    LOGV("RS Time Data: Idle %2.1f (%lli),  Internal %2.1f (%lli),  Script %2.1f (%lli),  Clear & Swap %2.1f (%lli)",
+    LOGV("RS: Frame (%lli),   Script %2.1f (%lli),  Clear & Swap %2.1f (%lli),  Idle %2.1f (%lli),  Internal %2.1f (%lli)",
+         frame / 1000000,
          100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
          100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
          100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
@@ -232,6 +243,7 @@
 #endif
              eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
 #if RS_LOG_TIMES
+             rsc->timerFrame();
              rsc->timerSet(RS_TIMER_INTERNAL);
              rsc->timerPrint();
              rsc->timerReset();
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index c58a88c..634416b 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -131,6 +131,7 @@
     void timerReset();
     void timerSet(Timers);
     void timerPrint();
+    void timerFrame();
 
     bool checkVersion1_1() const {return (mGL.mMajorVersion > 1) || (mGL.mMinorVersion >= 1); }
     bool checkVersion2_0() const {return mGL.mMajorVersion >= 2; }
@@ -202,6 +203,8 @@
     uint64_t mTimers[_RS_TIMER_TOTAL];
     Timers mTimerActive;
     uint64_t mTimeLast;
+    uint64_t mTimeFrame;
+    uint64_t mTimeLastFrame;
 };
 
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 0c7ac18..9d9eb1b 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -67,6 +67,12 @@
                 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     }
 
+    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+        if (mProgram.mSlotPointers[ct]) {
+            *mProgram.mSlotPointers[ct] = mSlots[ct]->getPtr();
+        }
+    }
+
     bool ret = false;
     tls->mScript = this;
     ret = mProgram.mScript(launchIndex) != 0;
@@ -139,6 +145,7 @@
     accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
     accCompileScript(mAccScript);
     accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
+    accGetScriptLabel(mAccScript, "init", (ACCvoid**) &mProgram.mInit);
     rsAssert(mProgram.mScript);
 
     if (!mProgram.mScript) {
@@ -148,6 +155,19 @@
         LOGE(buf);
     }
 
+    if (mProgram.mInit) {
+        mProgram.mInit();
+    }
+
+    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+        if (mSlotNames[ct].length() > 0) {
+            accGetScriptLabel(mAccScript,
+                              mSlotNames[ct].string(),
+                              (ACCvoid**) &mProgram.mSlotPointers[ct]);
+            LOGE("var  %s  %p", mSlotNames[ct].string(), mProgram.mSlotPointers[ct]);
+        }
+    }
+
     mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
     mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
     mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
@@ -224,6 +244,19 @@
     }
 }
 
+static void appendElementBody(String8 *s, const Element *e)
+{
+    s->append(" {\n");
+    for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
+        const Component *c = e->getComponent(ct2);
+        s->append("    ");
+        s->append(c->getCType());
+        s->append(" ");
+        s->append(c->getComponentName());
+        s->append(";\n");
+    }
+    s->append("}");
+}
 
 void ScriptCState::appendVarDefines(String8 *str)
 {
@@ -246,6 +279,8 @@
     }
 }
 
+
+
 void ScriptCState::appendTypes(String8 *str)
 {
     char buf[256];
@@ -257,6 +292,19 @@
             continue;
         }
         const Element *e = t->getElement();
+        if (e->getName() && (e->getComponentCount() > 1)) {
+            String8 s("struct struct_");
+            s.append(e->getName());
+            appendElementBody(&s, e);
+            s.append(";\n");
+            s.append("#define ");
+            s.append(e->getName());
+            s.append("_t struct struct_");
+            s.append(e->getName());
+            s.append("\n\n");
+            LOGD(s);
+            str->append(s);
+        }
 
         if (t->getName()) {
             for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
@@ -267,12 +315,39 @@
                 tmp.append(c->getComponentName());
                 sprintf(buf, " %i\n", ct2);
                 tmp.append(buf);
-                //LOGD(tmp);
+                LOGD(tmp);
                 str->append(tmp);
             }
         }
 
         if (mSlotNames[ct].length() > 0) {
+            String8 s;
+            if (e->getComponentCount() > 1) {
+                if (e->getName()) {
+                    // Use the named struct
+                    s.setTo(e->getName());
+                    s.append("_t *");
+                } else {
+                    // create an struct named from the slot.
+                    s.setTo("struct ");
+                    s.append(mSlotNames[ct]);
+                    s.append("_s");
+                    appendElementBody(&s, e);
+                    s.append(";\n");
+                    s.append("struct ");
+                    s.append(mSlotNames[ct]);
+                    s.append("_s * ");
+                }
+            } else {
+                // Just make an array
+                s.setTo(e->getComponent(0)->getCType());
+                s.append("_t *");
+            }
+            s.append(mSlotNames[ct]);
+            s.append(";\n");
+            LOGD(s);
+            str->append(s);
+#if 0
             for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
                 const Component *c = e->getComponent(ct2);
                 tmp.setTo("#define ");
@@ -295,12 +370,12 @@
                 sprintf(buf, "%i, %i)\n", ct, ct2);
                 tmp.append(buf);
 
-                //LOGD(tmp);
+                LOGD(tmp);
                 str->append(tmp);
             }
+#endif
         }
     }
-
 }
 
 
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 302515e..8aa99ef 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -35,6 +35,7 @@
 {
 public:
     typedef int (*RunScript_t)(uint32_t launchIndex);
+    typedef void (*VoidFunc_t)();
 
     ScriptC();
     virtual ~ScriptC();
@@ -48,6 +49,9 @@
         int mVersionMinor;
 
         RunScript_t mScript;
+        VoidFunc_t mInit;
+
+        void ** mSlotPointers[MAX_SCRIPT_BANKS];
     };
 
     Program_t mProgram;
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 55007ba..f67a7ae 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -25,6 +25,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.accessibilityservice.IEventListener;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -615,6 +616,10 @@
             mId = sIdCounter++;
             mComponentName = componentName;
             mIntent = new Intent().setComponent(mComponentName);
+            mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+                    com.android.internal.R.string.accessibility_binding_label);
+            mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                    mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
         }
 
         /**
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 558a024..1da2b47 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -32,6 +32,7 @@
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -765,6 +766,10 @@
         
         mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
         mCurIntent.setComponent(info.getComponent());
+        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+                com.android.internal.R.string.input_method_binding_label);
+        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
         if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE)) {
             mLastBindTime = SystemClock.uptimeMillis();
             mHaveConnection = true;
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index c101463..cc977b0 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -21,6 +21,7 @@
 
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
+import android.app.PendingIntent;
 import android.backup.BackupManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -40,6 +41,7 @@
 import android.os.RemoteCallbackList;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.service.wallpaper.IWallpaperConnection;
 import android.service.wallpaper.IWallpaperEngine;
 import android.service.wallpaper.IWallpaperService;
@@ -376,6 +378,10 @@
             // Bind the service!
             WallpaperConnection newConn = new WallpaperConnection();
             intent.setComponent(realName);
+            intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+                    com.android.internal.R.string.wallpaper_binding_label);
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                    mContext, 0, new Intent(Intent.ACTION_SET_WALLPAPER), 0));
             if (!mContext.bindService(intent, newConn,
                     Context.BIND_AUTO_CREATE)) {
                 throw new IllegalArgumentException("Unable to bind service: "
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 03ebf0c..9554a22 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -8866,6 +8866,16 @@
                     } else {
                         currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
                     }
+                    currApp.importanceReasonCode = app.adjTypeCode;
+                    if (app.adjSource instanceof ProcessRecord) {
+                        currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
+                    } else if (app.adjSource instanceof HistoryRecord) {
+                        HistoryRecord r = (HistoryRecord)app.adjSource;
+                        if (r.app != null) currApp.importanceReasonPid = r.app.pid;
+                    }
+                    if (app.adjTarget instanceof ComponentName) {
+                        currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
+                    }
                     //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
                     //        + " lru=" + currApp.lru);
                     if (runList == null) {
@@ -9888,6 +9898,13 @@
         if (r.app != null && r.app.persistent) {
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
         }
+        for (ConnectionRecord conn : r.connections.values()) {
+            if (conn.clientLabel != 0) {
+                info.clientPackage = conn.binding.client.info.packageName;
+                info.clientLabel = conn.clientLabel;
+                break;
+            }
+        }
         return info;
     }
     
@@ -9916,6 +9933,20 @@
         }
     }
 
+    public PendingIntent getRunningServiceControlPanel(ComponentName name) {
+        synchronized (this) {
+            ServiceRecord r = mServices.get(name);
+            if (r != null) {
+                for (ConnectionRecord conn : r.connections.values()) {
+                    if (conn.clientIntent != null) {
+                        return conn.clientIntent;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
     private final ServiceRecord findServiceLocked(ComponentName name,
             IBinder token) {
         ServiceRecord r = mServices.get(name);
@@ -10783,6 +10814,29 @@
                 activity = (HistoryRecord)mHistory.get(aindex);
             }
 
+            int clientLabel = 0;
+            PendingIntent clientIntent = null;
+            
+            if (callerApp.info.uid == Process.SYSTEM_UID) {
+                // Hacky kind of thing -- allow system stuff to tell us
+                // what they are, so we can report this elsewhere for
+                // others to know why certain services are running.
+                try {
+                    clientIntent = (PendingIntent)service.getParcelableExtra(
+                            Intent.EXTRA_CLIENT_INTENT);
+                } catch (RuntimeException e) {
+                }
+                if (clientIntent != null) {
+                    clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
+                    if (clientLabel != 0) {
+                        // There are no useful extras in the intent, trash them.
+                        // System code calling with this stuff just needs to know
+                        // this will happen.
+                        service = service.cloneFilter();
+                    }
+                }
+            }
+            
             ServiceLookupResult res =
                 retrieveServiceLocked(service, resolvedType,
                         Binder.getCallingPid(), Binder.getCallingUid());
@@ -10803,7 +10857,7 @@
 
             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
             ConnectionRecord c = new ConnectionRecord(b, activity,
-                    connection, flags);
+                    connection, flags, clientLabel, clientIntent);
 
             IBinder binder = connection.asBinder();
             s.connections.put(binder, c);
@@ -12776,6 +12830,7 @@
             return (app.curAdj=app.maxAdj);
        }
         
+        app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
         app.adjSource = null;
         app.adjTarget = null;
 
@@ -12909,6 +12964,8 @@
                                 adj = clientAdj > VISIBLE_APP_ADJ
                                         ? clientAdj : VISIBLE_APP_ADJ;
                                 app.adjType = "service";
+                                app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                        .REASON_SERVICE_IN_USE;
                                 app.adjSource = cr.binding.client;
                                 app.adjTarget = s.serviceInfo.name;
                             }
@@ -12922,6 +12979,8 @@
                                  || a.state == ActivityState.PAUSING)) {
                             adj = FOREGROUND_APP_ADJ;
                             app.adjType = "service";
+                            app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                    .REASON_SERVICE_IN_USE;
                             app.adjSource = a;
                             app.adjTarget = s.serviceInfo.name;
                         }
@@ -12964,6 +13023,8 @@
                             adj = clientAdj > FOREGROUND_APP_ADJ
                                     ? clientAdj : FOREGROUND_APP_ADJ;
                             app.adjType = "provider";
+                            app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                    .REASON_PROVIDER_IN_USE;
                             app.adjSource = client;
                             app.adjTarget = cpr.info.name;
                         }
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index b3343dd..f613b00 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import android.app.IServiceConnection;
+import android.app.PendingIntent;
 
 import java.io.PrintWriter;
 
@@ -28,6 +29,8 @@
     final HistoryRecord activity;   // If non-null, the owning activity.
     final IServiceConnection conn;  // The client connection.
     final int flags;                // Binding options.
+    final int clientLabel;          // String resource labeling this client.
+    final PendingIntent clientIntent; // How to launch the client.
     String stringName;              // Caching of toString.
     
     void dump(PrintWriter pw, String prefix) {
@@ -40,11 +43,14 @@
     }
     
     ConnectionRecord(AppBindRecord _binding, HistoryRecord _activity,
-               IServiceConnection _conn, int _flags) {
+               IServiceConnection _conn, int _flags,
+               int _clientLabel, PendingIntent _clientIntent) {
         binding = _binding;
         activity = _activity;
         conn = _conn;
         flags = _flags;
+        clientLabel = _clientLabel;
+        clientIntent = _clientIntent;
     }
 
     public String toString() {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 76fdf09..d05b44b 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -75,6 +75,7 @@
     boolean reportLowMemory;    // Set to true when waiting to report low mem
     int lastPss;                // Last pss size reported by app.
     String adjType;             // Debugging: primary thing impacting oom_adj.
+    int adjTypeCode;            // Debugging: adj code to report to app.
     Object adjSource;           // Debugging: option dependent object.
     Object adjTarget;           // Debugging: target component impacting oom_adj.
     
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a690e3c..a744486 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -484,7 +484,12 @@
      * @return true if a ICC card is present
      */
     public boolean hasIccCard() {
-        return PhoneFactory.getDefaultPhone().getIccCard().hasIccCard();
+        try {
+            return getITelephony().hasIccCard();
+        } catch (RemoteException ex) {
+            // Assume no ICC card if remote exception which shouldn't happen
+            return false;
+        }
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java
index 5f40579..0896ba6 100644
--- a/telephony/java/com/android/internal/telephony/AdnRecord.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecord.java
@@ -23,6 +23,8 @@
 
 import com.android.internal.telephony.GsmAlphabet;
 
+import java.util.Arrays;
+
 
 /**
  *
@@ -38,6 +40,7 @@
 
     String alphaTag = "";
     String number = "";
+    String[] emails;
     int extRecord = 0xff;
     int efid;                   // or 0 if none
     int recordNumber;           // or 0 if none
@@ -74,13 +77,15 @@
             int recordNumber;
             String alphaTag;
             String number;
+            String[] emails;
 
             efid = source.readInt();
             recordNumber = source.readInt();
             alphaTag = source.readString();
             number = source.readString();
+            emails = source.readStringArray();
 
-            return new AdnRecord(efid, recordNumber, alphaTag, number);
+            return new AdnRecord(efid, recordNumber, alphaTag, number, emails);
         }
 
         public AdnRecord[] newArray(int size) {
@@ -90,29 +95,38 @@
 
 
     //***** Constructor
-    public
-    AdnRecord (byte[] record) {
+    public AdnRecord (byte[] record) {
         this(0, 0, record);
     }
 
-    public
-    AdnRecord (int efid, int recordNumber, byte[] record) {
+    public AdnRecord (int efid, int recordNumber, byte[] record) {
         this.efid = efid;
         this.recordNumber = recordNumber;
         parseRecord(record);
     }
 
-    public
-    AdnRecord (String alphaTag, String number) {
+    public AdnRecord (String alphaTag, String number) {
         this(0, 0, alphaTag, number);
     }
 
-    public
-    AdnRecord (int efid, int recordNumber, String alphaTag, String number) {
+    public AdnRecord (String alphaTag, String number, String[] emails) {
+        this(0, 0, alphaTag, number, emails);
+    }
+
+    public AdnRecord (int efid, int recordNumber, String alphaTag, String number, String[] emails) {
         this.efid = efid;
         this.recordNumber = recordNumber;
         this.alphaTag = alphaTag;
         this.number = number;
+        this.emails = emails;
+    }
+
+    public AdnRecord(int efid, int recordNumber, String alphaTag, String number) {
+        this.efid = efid;
+        this.recordNumber = recordNumber;
+        this.alphaTag = alphaTag;
+        this.number = number;
+        this.emails = null;
     }
 
     //***** Instance Methods
@@ -125,12 +139,20 @@
         return number;
     }
 
+    public String[] getEmails() {
+        return emails;
+    }
+
+    public void setEmails(String[] emails) {
+        this.emails = emails;
+    }
+
     public String toString() {
-        return "ADN Record '" + alphaTag + "' '" + number + "'";
+        return "ADN Record '" + alphaTag + "' '" + number + " " + emails + "'";
     }
 
     public boolean isEmpty() {
-        return alphaTag.equals("") && number.equals("");
+        return alphaTag.equals("") && number.equals("") && emails == null;
     }
 
     public boolean hasExtendedRecord() {
@@ -139,7 +161,8 @@
 
     public boolean isEqual(AdnRecord adn) {
         return ( alphaTag.equals(adn.getAlphaTag()) &&
-                number.equals(adn.getNumber()) );
+                number.equals(adn.getNumber()) &&
+                Arrays.equals(emails, adn.getEmails()));
     }
     //***** Parcelable Implementation
 
@@ -152,6 +175,7 @@
         dest.writeInt(recordNumber);
         dest.writeString(alphaTag);
         dest.writeString(number);
+        dest.writeStringArray(emails);
     }
 
     /**
@@ -274,10 +298,13 @@
 
             extRecord = 0xff & record[record.length - 1];
 
+            emails = null;
+
         } catch (RuntimeException ex) {
             Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
             number = "";
             alphaTag = "";
+            emails = null;
         }
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/AdnRecordCache.java b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
index c270ae5..c8c0658 100644
--- a/telephony/java/com/android/internal/telephony/AdnRecordCache.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
@@ -16,14 +16,16 @@
 
 package com.android.internal.telephony;
 
-import android.util.SparseArray;
-import android.util.Log;
-import android.os.Message;
-import android.os.Handler;
 import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.telephony.gsm.UsimPhoneBookManager;
+
 import java.util.ArrayList;
 import java.util.Iterator;
-import com.android.internal.telephony.IccConstants;
 
 /**
  * {@hide}
@@ -32,6 +34,7 @@
     //***** Instance Variables
 
     PhoneBase phone;
+    private UsimPhoneBookManager mUsimPhoneBookManager;
 
     // Indexed by EF ID
     SparseArray<ArrayList<AdnRecord>> adnLikeFiles
@@ -55,6 +58,7 @@
 
     public AdnRecordCache(PhoneBase phone) {
         this.phone = phone;
+        mUsimPhoneBookManager = new UsimPhoneBookManager(phone, this);
     }
 
     //***** Called from SIMRecords
@@ -64,6 +68,7 @@
      */
     public void reset() {
         adnLikeFiles.clear();
+        mUsimPhoneBookManager.reset();
 
         clearWaiters();
         clearUserWriters();
@@ -103,14 +108,14 @@
      *
      * See 3GPP TS 51.011 for this mapping
      */
-    private int
-    extensionEfForEf(int efid) {
+    int extensionEfForEf(int efid) {
         switch (efid) {
             case EF_MBDN: return EF_EXT6;
             case EF_ADN: return EF_EXT1;
             case EF_SDN: return EF_EXT3;
             case EF_FDN: return EF_EXT2;
             case EF_MSISDN: return EF_EXT1;
+            case EF_PBR: return 0; // The EF PBR doesn't have an extension record
             default: return -1;
         }
     }
@@ -223,11 +228,15 @@
      * record
      */
     public void
-    requestLoadAllAdnLike (int efid, Message response) {
+    requestLoadAllAdnLike (int efid, int extensionEf, Message response) {
         ArrayList<Message> waiters;
         ArrayList<AdnRecord> result;
 
-        result = getRecordsIfLoaded(efid);
+        if (efid == EF_PBR) {
+            result = mUsimPhoneBookManager.loadEfFilesFromUsim();
+        } else {
+            result = getRecordsIfLoaded(efid);
+        }
 
         // Have we already loaded this efid?
         if (result != null) {
@@ -258,9 +267,8 @@
 
         adnLikeWaiters.put(efid, waiters);
 
-        int extensionEF = extensionEfForEf(efid);
 
-        if (extensionEF < 0) {
+        if (extensionEf < 0) {
             // respond with error if not known ADN-like record
 
             if (response != null) {
@@ -272,7 +280,7 @@
             return;
         }
 
-        new AdnRecordLoader(phone).loadAllFromEF(efid, extensionEF,
+        new AdnRecordLoader(phone).loadAllFromEF(efid, extensionEf,
             obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE, efid, 0));
     }
 
@@ -311,7 +319,7 @@
                 adnLikeWaiters.delete(efid);
 
                 if (ar.exception == null) {
-                    adnLikeFiles.put(efid, (ArrayList<AdnRecord>) (ar.result));
+                    adnLikeFiles.put(efid, (ArrayList<AdnRecord>) ar.result);
                 }
                 notifyWaiters(waiters, ar);
                 break;
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 63c23ae..2328717 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -252,5 +252,10 @@
       * Returns the network type
       */
     int getNetworkType();
+    
+    /**
+     * Return true if an ICC card is present
+     */
+    boolean hasIccCard();
 }
 
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 200340e..0f76633 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -655,7 +655,7 @@
     }
 
 
-    public boolean hasApplicationType(IccCardApplication.AppType type) {
+    public boolean isApplicationOnIcc(IccCardApplication.AppType type) {
         if (mIccCardStatus == null) return false;
 
         for (int i = 0 ; i < mIccCardStatus.getNumApplications(); i++) {
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index 7eafafd..acc9197 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -42,6 +42,9 @@
     static final int EF_CFIS = 0x6FCB;
     static final int EF_IMG = 0x4f20;
 
+    // USIM SIM file ids from TS 31.102
+    public static final int EF_PBR = 0x4F30;
+
     // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
     static final int EF_MAILBOX_CPHS = 0x6F17;
     static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
@@ -59,6 +62,7 @@
 
     static final String MF_SIM = "3F00";
     static final String DF_TELECOM = "7F10";
+    static final String DF_PHONEBOOK = "5F3A";
     static final String DF_GRAPHICS = "5F50";
     static final String DF_GSM = "7F20";
     static final String DF_CDMA = "7F25";
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 0bcaaa6..31cf6a7 100644
--- a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -115,7 +115,8 @@
      * Replace oldAdn with newAdn in ADN-like record in EF
      *
      * getAdnRecordsInEf must be called at least once before this function,
-     * otherwise an error will be returned
+     * otherwise an error will be returned. Currently the email field
+     * if set in the ADN record is ignored.
      * throws SecurityException if no WRITE_CONTACTS permission
      *
      * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
@@ -167,7 +168,8 @@
      * Update an ADN-like EF record by record index
      *
      * This is useful for iteration the whole ADN file, such as write the whole
-     * phone book or erase/format the whole phonebook
+     * phone book or erase/format the whole phonebook. Currently the email field
+     * if set in the ADN record is ignored.
      * throws SecurityException if no WRITE_CONTACTS permission
      *
      * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
@@ -237,12 +239,13 @@
                     "Requires android.permission.READ_CONTACTS permission");
         }
 
+        efid = updateEfForIccType(efid);
         if (DBG) logd("getAdnRecordsInEF: efid=" + efid);
 
         synchronized(mLock) {
             checkThread();
             Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
-            adnCache.requestLoadAllAdnLike(efid, response);
+            adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
@@ -262,5 +265,15 @@
             }
         }
     }
+
+    private int updateEfForIccType(int efid) {
+        // Check if we are trying to read ADN records
+        if (efid == IccConstants.EF_ADN) {
+            if (phone.getIccCard().isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
+                return IccConstants.EF_PBR;
+            }
+        }
+        return efid;
+    }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
index 4cbd779..ffcfe6f 100644
--- a/telephony/java/com/android/internal/telephony/IccProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -46,7 +46,8 @@
 
     private static final String[] ADDRESS_BOOK_COLUMN_NAMES = new String[] {
         "name",
-        "number"
+        "number",
+        "emails"
     };
 
     private static final int ADN = 1;
@@ -55,6 +56,7 @@
 
     private static final String STR_TAG = "tag";
     private static final String STR_NUMBER = "number";
+    private static final String STR_EMAILS = "emails";
     private static final String STR_PIN2 = "pin2";
 
     private static final UriMatcher URL_MATCHER =
@@ -172,7 +174,8 @@
 
         String tag = initialValues.getAsString("tag");
         String number = initialValues.getAsString("number");
-        boolean success = addIccRecordToEf(efType, tag, number, pin2);
+        // TODO(): Read email instead of sending null.
+        boolean success = addIccRecordToEf(efType, tag, number, null, pin2);
 
         if (!success) {
             return null;
@@ -238,6 +241,7 @@
         // parse where clause
         String tag = null;
         String number = null;
+        String[] emails = null;
         String pin2 = null;
 
         String[] tokens = where.split("AND");
@@ -261,6 +265,9 @@
                 tag = normalizeValue(val);
             } else if (STR_NUMBER.equals(key)) {
                 number = normalizeValue(val);
+            } else if (STR_EMAILS.equals(key)) {
+                //TODO(): Email is null.
+                emails = null;
             } else if (STR_PIN2.equals(key)) {
                 pin2 = normalizeValue(val);
             }
@@ -274,7 +281,7 @@
             return 0;
         }
 
-        boolean success = deleteIccRecordFromEf(efType, tag, number, pin2);
+        boolean success = deleteIccRecordFromEf(efType, tag, number, emails, pin2);
         if (!success) {
             return 0;
         }
@@ -307,9 +314,11 @@
 
         String tag = values.getAsString("tag");
         String number = values.getAsString("number");
+        String[] emails = null;
         String newTag = values.getAsString("newTag");
         String newNumber = values.getAsString("newNumber");
-
+        String[] newEmails = null;
+        // TODO(): Update for email.
         boolean success = updateIccRecordInEf(efType, tag, number,
                 newTag, newNumber, pin2);
 
@@ -355,9 +364,9 @@
     }
 
     private boolean
-    addIccRecordToEf(int efType, String name, String number, String pin2) {
+    addIccRecordToEf(int efType, String name, String number, String[] emails, String pin2) {
         if (DBG) log("addIccRecordToEf: efType=" + efType + ", name=" + name +
-                ", number=" + number);
+                ", number=" + number + ", emails=" + emails);
 
         boolean success = false;
 
@@ -384,7 +393,7 @@
 
     private boolean
     updateIccRecordInEf(int efType, String oldName, String oldNumber,
-            String newName, String newNumber,String pin2) {
+            String newName, String newNumber, String pin2) {
         if (DBG) log("updateIccRecordInEf: efType=" + efType +
                 ", oldname=" + oldName + ", oldnumber=" + oldNumber +
                 ", newname=" + newName + ", newnumber=" + newNumber);
@@ -407,9 +416,10 @@
     }
 
 
-    private boolean deleteIccRecordFromEf(int efType, String name, String number, String pin2) {
+    private boolean deleteIccRecordFromEf(int efType, String name, String number, String[] emails,
+            String pin2) {
         if (DBG) log("deleteIccRecordFromEf: efType=" + efType +
-                ", name=" + name + ", number=" + number + ", pin2=" + pin2);
+                ", name=" + name + ", number=" + number + ", emails=" + emails + ", pin2=" + pin2);
 
         boolean success = false;
 
@@ -438,13 +448,26 @@
     private void loadRecord(AdnRecord record,
             ArrayList<ArrayList> results) {
         if (!record.isEmpty()) {
-            ArrayList<String> contact = new ArrayList<String>(2);
+            ArrayList<String> contact = new ArrayList<String>();
             String alphaTag = record.getAlphaTag();
             String number = record.getNumber();
+            String[] emails = record.getEmails();
 
-            if (DBG) log("loadRecord: " + alphaTag + ", " + number);
+            if (DBG) log("loadRecord: " + alphaTag + ", " + number + ",");
             contact.add(alphaTag);
             contact.add(number);
+            StringBuilder emailString = new StringBuilder();
+
+            if (emails != null) {
+                for (String email: emails) {
+                    if (DBG) log("Adding email:" + email);
+                    emailString.append(email);
+                    emailString.append(",");
+                }
+                contact.add(emailString.toString());
+            } else {
+                contact.add(null);
+            }
             results.add(contact);
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
index a08cdde..206e62f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
@@ -19,15 +19,18 @@
 import android.os.Message;
 import android.util.Log;
 
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccCardApplication;
 import com.android.internal.telephony.IccConstants;
 import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.Phone;
 
 /**
  * {@hide}
  */
 public final class SIMFileHandler extends IccFileHandler implements IccConstants {
     static final String LOG_TAG = "GSM";
-
+    private Phone mPhone;
 
     //***** Instance Variables
 
@@ -35,6 +38,7 @@
 
     SIMFileHandler(GSMPhone phone) {
         super(phone);
+        mPhone = phone;
     }
 
     public void dispose() {
@@ -53,7 +57,6 @@
     }
 
     protected String getEFPath(int efid) {
-        // TODO(): Make changes when USIM is supported
         // TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility.
         // Implement this after discussion with OEMs.
         switch(efid) {
@@ -79,8 +82,23 @@
         case EF_SPN_SHORT_CPHS:
         case EF_INFO_CPHS:
             return MF_SIM + DF_GSM;
+
+        case EF_PBR:
+            // we only support global phonebook.
+            return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
         }
-        return getCommonIccEFPath(efid);
+        String path = getCommonIccEFPath(efid);
+        if (path == null) {
+            // The EFids in USIM phone book entries are decided by the card manufacturer.
+            // So if we don't match any of the cases above and if its a USIM return
+            // the phone book path.
+            IccCard card = phone.getIccCard();
+            if (card != null && card.isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
+                return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
+            }
+            Log.e(LOG_TAG, "Error: EF Path being returned in null");
+        }
+        return path;
     }
 
     protected void logd(String msg) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
index 30543c7..497cf5f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
@@ -47,7 +47,6 @@
 
     public boolean nextObject() {
         if (!hasValidTlvObject) return false;
-
         curOffset = curDataOffset + curDataLength;
         hasValidTlvObject = parseCurrentTlvObject();
         return hasValidTlvObject;
@@ -88,11 +87,12 @@
 
     private boolean parseCurrentTlvObject() {
         // 0x00 and 0xff are invalid tag values
-        if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
-            return false;
-        }
 
         try {
+            if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
+                return false;
+            }
+
             if ((record[curOffset + 1] & 0xff) < 0x80) {
                 // one byte length 0 - 0x7f
                 curDataLength = record[curOffset + 1] & 0xff;
diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
new file mode 100644
index 0000000..d27f240
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneBase;
+
+import org.apache.harmony.luni.lang.reflect.ListOfTypes;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class implements reading and parsing USIM records.
+ * Refer to Spec 3GPP TS 31.102 for more details.
+ *
+ * {@hide}
+ */
+public class UsimPhoneBookManager extends Handler implements IccConstants {
+    private static final String LOG_TAG = "GSM";
+    private static final boolean DBG = true;
+    private PbrFile mPbrFile;
+    private Boolean mIsPbrPresent;
+    private PhoneBase mPhone;
+    private AdnRecordCache mAdnCache;
+    private Object mLock = new Object();
+    private ArrayList<AdnRecord> mPhoneBookRecords;
+    private boolean mEmailPresentInIap = false;
+    private int mEmailTagNumberInIap = 0;
+    private ArrayList<byte[]> mIapFileRecord;
+    private ArrayList<byte[]> mEmailFileRecord;
+    private Map<Integer, ArrayList<String>> mEmailsForAdnRec;
+
+    private static final int EVENT_PBR_LOAD_DONE = 1;
+    private static final int EVENT_USIM_ADN_LOAD_DONE = 2;
+    private static final int EVENT_IAP_LOAD_DONE = 3;
+    private static final int EVENT_EMAIL_LOAD_DONE = 4;
+
+    private static final int USIM_TYPE1_TAG   = 0xA8;
+    private static final int USIM_TYPE2_TAG   = 0xA9;
+    private static final int USIM_TYPE3_TAG   = 0xAA;
+    private static final int USIM_EFADN_TAG   = 0xC0;
+    private static final int USIM_EFIAP_TAG   = 0xC1;
+    private static final int USIM_EFEXT1_TAG  = 0xC2;
+    private static final int USIM_EFSNE_TAG   = 0xC3;
+    private static final int USIM_EFANR_TAG   = 0xC4;
+    private static final int USIM_EFPBC_TAG   = 0xC5;
+    private static final int USIM_EFGRP_TAG   = 0xC6;
+    private static final int USIM_EFAAS_TAG   = 0xC7;
+    private static final int USIM_EFGSD_TAG   = 0xC8;
+    private static final int USIM_EFUID_TAG   = 0xC9;
+    private static final int USIM_EFEMAIL_TAG = 0xCA;
+    private static final int USIM_EFCCP1_TAG  = 0xCB;
+
+    public UsimPhoneBookManager(PhoneBase phone, AdnRecordCache cache) {
+        mPhone = phone;
+        mPhoneBookRecords = new ArrayList<AdnRecord>();
+        mPbrFile = null;
+        // We assume its present, after the first read this is updated.
+        // So we don't have to read from UICC if its not present on subsequent reads.
+        mIsPbrPresent = true;
+        mAdnCache = cache;
+    }
+
+    public void reset() {
+        mPhoneBookRecords.clear();
+        mIapFileRecord = null;
+        mEmailFileRecord = null;
+        mPbrFile = null;
+        mIsPbrPresent = true;
+    }
+
+    public ArrayList<AdnRecord> loadEfFilesFromUsim() {
+        synchronized (mLock) {
+            if (!mPhoneBookRecords.isEmpty()) return mPhoneBookRecords;
+            if (!mIsPbrPresent) return null;
+
+            // Check if the PBR file is present in the cache, if not read it
+            // from the USIM.
+            if (mPbrFile == null) {
+                readPbrFileAndWait();
+            }
+
+            if (mPbrFile == null) return null;
+
+            int numRecs = mPbrFile.mFileIds.size();
+            for (int i = 0; i < numRecs; i++) {
+                readAdnFileAndWait(i);
+                readEmailFileAndWait(i);
+            }
+            // All EF files are loaded, post the response.
+        }
+        return mPhoneBookRecords;
+    }
+
+    private void readPbrFileAndWait() {
+        mPhone.getIccFileHandler().loadEFLinearFixedAll(EF_PBR, obtainMessage(EVENT_PBR_LOAD_DONE));
+        try {
+            mLock.wait();
+        } catch (InterruptedException e) {
+            Log.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait");
+        }
+    }
+
+    private void readEmailFileAndWait(int recNum) {
+        Map <Integer,Integer> fileIds;
+        fileIds = mPbrFile.mFileIds.get(recNum);
+        if (fileIds == null) return;
+
+        if (fileIds.containsKey(USIM_EFEMAIL_TAG)) {
+            int efid = fileIds.get(USIM_EFEMAIL_TAG);
+            // Check if the EFEmail is a Type 1 file or a type 2 file.
+            // If mEmailPresentInIap is true, its a type 2 file.
+            // So we read the IAP file and then read the email records.
+            // instead of reading directly.
+            if (mEmailPresentInIap) {
+                readIapFileAndWait(fileIds.get(USIM_EFIAP_TAG));
+                if (mIapFileRecord == null) {
+                    Log.e(LOG_TAG, "Error: IAP file is empty");
+                    return;
+                }
+            }
+            // Read the EFEmail file.
+            mPhone.getIccFileHandler().loadEFLinearFixedAll(fileIds.get(USIM_EFEMAIL_TAG),
+                    obtainMessage(EVENT_EMAIL_LOAD_DONE));
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                Log.e(LOG_TAG, "Interrupted Exception in readEmailFileAndWait");
+            }
+
+            if (mEmailFileRecord == null) {
+                Log.e(LOG_TAG, "Error: Email file is empty");
+                return;
+            }
+            updatePhoneAdnRecord();
+        }
+
+    }
+
+    private void readIapFileAndWait(int efid) {
+        mPhone.getIccFileHandler().loadEFLinearFixedAll(efid, obtainMessage(EVENT_IAP_LOAD_DONE));
+        try {
+            mLock.wait();
+        } catch (InterruptedException e) {
+            Log.e(LOG_TAG, "Interrupted Exception in readIapFileAndWait");
+        }
+    }
+
+    private void updatePhoneAdnRecord() {
+        if (mEmailFileRecord == null) return;
+        int numAdnRecs = mPhoneBookRecords.size();
+        if (mIapFileRecord != null) {
+            // The number of records in the IAP file is same as the number of records in ADN file.
+            // The order of the pointers in an EFIAP shall be the same as the order of file IDs
+            // that appear in the TLV object indicated by Tag 'A9' in the reference file record.
+            // i.e value of mEmailTagNumberInIap
+
+            for (int i = 0; i < numAdnRecs; i++) {
+                byte[] record = null;
+                try {
+                    record = mIapFileRecord.get(i);
+                } catch (IndexOutOfBoundsException e) {
+                    Log.e(LOG_TAG, "Error: Improper ICC card: No IAP record for ADN, continuing");
+                    break;
+                }
+                int recNum = record[mEmailTagNumberInIap];
+
+                if (recNum != -1) {
+                    String[] emails = new String[1];
+                    // SIM record numbers are 1 based
+                    emails[0] = readEmailRecord(recNum - 1);
+                    AdnRecord rec = mPhoneBookRecords.get(i);
+                    if (rec != null) {
+                        rec.setEmails(emails);
+                    } else {
+                        // might be a record with only email
+                        rec = new AdnRecord("", "", emails);
+                    }
+                    mPhoneBookRecords.set(i, rec);
+                }
+            }
+        }
+
+        // ICC cards can be made such that they have an IAP file but all
+        // records are empty. So we read both type 1 and type 2 file
+        // email records, just to be sure.
+
+        int len = mPhoneBookRecords.size();
+        // Type 1 file, the number of records is the same as the number of
+        // records in the ADN file.
+        if (mEmailsForAdnRec == null) {
+            parseType1EmailFile(len);
+        }
+        for (int i = 0; i < numAdnRecs; i++) {
+            ArrayList<String> emailList = null;
+            try {
+                emailList = mEmailsForAdnRec.get(i);
+            } catch (IndexOutOfBoundsException e) {
+                break;
+            }
+            if (emailList == null) continue;
+
+            AdnRecord rec = mPhoneBookRecords.get(i);
+
+            String[] emails = new String[emailList.size()];
+            System.arraycopy(emailList.toArray(), 0, emails, 0, emailList.size());
+            rec.setEmails(emails);
+            mPhoneBookRecords.set(i, rec);
+        }
+    }
+
+    void parseType1EmailFile(int numRecs) {
+        mEmailsForAdnRec = new HashMap<Integer, ArrayList<String>>();
+        byte[] emailRec = null;
+        for (int i = 0; i < numRecs; i++) {
+            try {
+                emailRec = mEmailFileRecord.get(i);
+            } catch (IndexOutOfBoundsException e) {
+                Log.e(LOG_TAG, "Error: Improper ICC card: No email record for ADN, continuing");
+                break;
+            }
+            int adnRecNum = emailRec[emailRec.length - 1];
+
+            if (adnRecNum == -1) {
+                continue;
+            }
+
+            String email = readEmailRecord(i);
+
+            if (email == null || email.equals("")) {
+                continue;
+            }
+
+            // SIM record numbers are 1 based.
+            ArrayList<String> val = mEmailsForAdnRec.get(adnRecNum - 1);
+            if (val == null) {
+                val = new ArrayList<String>();
+            }
+            val.add(email);
+            // SIM record numbers are 1 based.
+            mEmailsForAdnRec.put(adnRecNum - 1, val);
+        }
+    }
+
+    private String readEmailRecord(int recNum) {
+        byte[] emailRec = null;
+        try {
+            emailRec = mEmailFileRecord.get(recNum);
+        } catch (IndexOutOfBoundsException e) {
+            return null;
+        }
+
+        // The length of the record is X+2 byte, where X bytes is the email address
+        String email = IccUtils.adnStringFieldToString(emailRec, 0, emailRec.length - 2);
+        return email;
+    }
+
+    private void readAdnFileAndWait(int recNum) {
+        Map <Integer,Integer> fileIds;
+        fileIds = mPbrFile.mFileIds.get(recNum);
+        if (fileIds == null) return;
+
+        mAdnCache.requestLoadAllAdnLike(fileIds.get(USIM_EFADN_TAG),
+            fileIds.get(USIM_EFEXT1_TAG), obtainMessage(EVENT_USIM_ADN_LOAD_DONE));
+        try {
+            mLock.wait();
+        } catch (InterruptedException e) {
+            Log.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait");
+        }
+    }
+
+    private void createPbrFile(ArrayList<byte[]> records) {
+        if (records == null) {
+            mPbrFile = null;
+            mIsPbrPresent = false;
+            return;
+        }
+        mPbrFile = new PbrFile(records);
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        switch(msg.what) {
+        case EVENT_PBR_LOAD_DONE:
+            ar = (AsyncResult) msg.obj;
+            if (ar.exception == null) {
+                createPbrFile((ArrayList<byte[]>)ar.result);
+            }
+            synchronized (mLock) {
+                mLock.notify();
+            }
+            break;
+        case EVENT_USIM_ADN_LOAD_DONE:
+            log("Loading USIM ADN records done");
+            ar = (AsyncResult) msg.obj;
+            if (ar.exception == null) {
+                mPhoneBookRecords.addAll((ArrayList<AdnRecord>)ar.result);
+            }
+            synchronized (mLock) {
+                mLock.notify();
+            }
+            break;
+        case EVENT_IAP_LOAD_DONE:
+            log("Loading USIM IAP records done");
+            ar = (AsyncResult) msg.obj;
+            if (ar.exception == null) {
+                mIapFileRecord = ((ArrayList<byte[]>)ar.result);
+            }
+            synchronized (mLock) {
+                mLock.notify();
+            }
+            break;
+        case EVENT_EMAIL_LOAD_DONE:
+            log("Loading USIM Email records done");
+            ar = (AsyncResult) msg.obj;
+            if (ar.exception == null) {
+                mEmailFileRecord = ((ArrayList<byte[]>)ar.result);
+            }
+
+            synchronized (mLock) {
+                mLock.notify();
+            }
+            break;
+        }
+    }
+
+    private class PbrFile {
+        // RecNum <EF Tag, efid>
+        HashMap<Integer,Map<Integer,Integer>> mFileIds;
+
+        PbrFile(ArrayList<byte[]> records) {
+            mFileIds = new HashMap<Integer, Map<Integer, Integer>>();
+            SimTlv recTlv;
+            int recNum = 0;
+            for (byte[] record: records) {
+                recTlv = new SimTlv(record, 0, record.length);
+                parseTag(recTlv, recNum);
+                recNum ++;
+            }
+        }
+
+        void parseTag(SimTlv tlv, int recNum) {
+            SimTlv tlvEf;
+            int tag;
+            byte[] data;
+            Map<Integer, Integer> val = new HashMap<Integer, Integer>();
+            do {
+                tag = tlv.getTag();
+                switch(tag) {
+                case USIM_TYPE1_TAG: // A8
+                case USIM_TYPE3_TAG: // AA
+                case USIM_TYPE2_TAG: // A9
+                    data = tlv.getData();
+                    tlvEf = new SimTlv(data, 0, data.length);
+                    parseEf(tlvEf, val, tag);
+                    break;
+                }
+            } while (tlv.nextObject());
+            mFileIds.put(recNum, val);
+        }
+
+        void parseEf(SimTlv tlv, Map<Integer, Integer> val, int parentTag) {
+            int tag;
+            byte[] data;
+            int tagNumberWithinParentTag = 0;
+            do {
+                tag = tlv.getTag();
+                if (parentTag == USIM_TYPE2_TAG && tag == USIM_EFEMAIL_TAG) {
+                    mEmailPresentInIap = true;
+                    mEmailTagNumberInIap = tagNumberWithinParentTag;
+                }
+                switch(tag) {
+                    case USIM_EFEMAIL_TAG:
+                    case USIM_EFADN_TAG:
+                    case USIM_EFEXT1_TAG:
+                    case USIM_EFANR_TAG:
+                    case USIM_EFPBC_TAG:
+                    case USIM_EFGRP_TAG:
+                    case USIM_EFAAS_TAG:
+                    case USIM_EFGSD_TAG:
+                    case USIM_EFUID_TAG:
+                    case USIM_EFCCP1_TAG:
+                    case USIM_EFIAP_TAG:
+                    case USIM_EFSNE_TAG:
+                        data = tlv.getData();
+                        int efid = data[0] << 8 | data[1];
+                        val.put(tag, efid);
+                        break;
+                }
+                tagNumberWithinParentTag ++;
+            } while(tlv.nextObject());
+        }
+    }
+
+    private void log(String msg) {
+        if(DBG) Log.d(LOG_TAG, msg);
+    }
+}