Merge "Revert "fix a weird use of Vector::appendVector()""
diff --git a/api/current.txt b/api/current.txt
index 46cf2af..d3333f0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -377,9 +377,11 @@
     field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
     field public static final int drawable = 16843161; // 0x1010199
     field public static final int drawableBottom = 16843118; // 0x101016e
+    field public static final int drawableEnd = 16843687; // 0x10103a7
     field public static final int drawableLeft = 16843119; // 0x101016f
     field public static final int drawablePadding = 16843121; // 0x1010171
     field public static final int drawableRight = 16843120; // 0x1010170
+    field public static final int drawableStart = 16843686; // 0x10103a6
     field public static final int drawableTop = 16843117; // 0x101016d
     field public static final int drawingCacheQuality = 16842984; // 0x10100e8
     field public static final int dropDownAnchor = 16843363; // 0x1010263
@@ -16007,6 +16009,7 @@
 
   protected static abstract interface ContactsContract.GroupsColumns {
     field public static final java.lang.String AUTO_ADD = "auto_add";
+    field public static final java.lang.String DATA_SET = "data_set";
     field public static final java.lang.String DELETED = "deleted";
     field public static final java.lang.String FAVORITES = "favorites";
     field public static final java.lang.String GROUP_IS_READ_ONLY = "group_is_read_only";
@@ -16134,6 +16137,7 @@
   protected static abstract interface ContactsContract.RawContactsColumns {
     field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
     field public static final java.lang.String CONTACT_ID = "contact_id";
+    field public static final java.lang.String DATA_SET = "data_set";
     field public static final java.lang.String DELETED = "deleted";
     field public static final java.lang.String RAW_CONTACT_IS_READ_ONLY = "raw_contact_is_read_only";
     field public static final java.lang.String RAW_CONTACT_IS_USER_PROFILE = "raw_contact_is_user_profile";
@@ -20902,8 +20906,10 @@
 
   public abstract class ActionProvider {
     ctor public ActionProvider(android.content.Context);
+    method public boolean hasSubMenu();
     method public abstract android.view.View onCreateActionView();
-    method public void onPerformDefaultAction(android.view.View);
+    method public boolean onPerformDefaultAction();
+    method public void onPrepareSubMenu(android.view.SubMenu);
   }
 
   public abstract interface ContextMenu implements android.view.Menu {
@@ -26417,7 +26423,9 @@
     method protected void onTextChanged(java.lang.CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
+    method protected void resetResolvedDrawables();
     method protected void resetResolvedLayoutDirection();
+    method protected void resolveDrawables();
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 479b70a..3fb1736 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -157,6 +157,11 @@
                 String value = nextArgRequired();
                 intent.putExtra(key, Integer.valueOf(value));
                 hasIntentInfo = true;
+            } else if (opt.equals("--eu")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, Uri.parse(value));
+                hasIntentInfo = true;
             } else if (opt.equals("--eia")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
@@ -1119,6 +1124,7 @@
                 "    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
                 "    [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
                 "    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+                "    [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
                 "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
                 "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
                 "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index a00a212..7d39912 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -5,13 +5,6 @@
 	bootanimation_main.cpp \
 	BootAnimation.cpp
 
-# need "-lrt" on Linux simulator to pick up clock_gettime
-ifeq ($(TARGET_SIMULATOR),true)
-	ifeq ($(HOST_OS),linux)
-		LOCAL_LDLIBS += -lrt
-	endif
-endif
-
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/cmds/bugreport/Android.mk b/cmds/bugreport/Android.mk
index 631c219..f476f5e 100644
--- a/cmds/bugreport/Android.mk
+++ b/cmds/bugreport/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -10,5 +8,3 @@
 LOCAL_SHARED_LIBRARIES := libcutils
 
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 431a556..56f1324 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -14,5 +12,3 @@
 LOCAL_SHARED_LIBRARIES := libcutils
 
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index d7a9ef6..f277339 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 
 common_src_files := \
@@ -41,5 +39,3 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
-
-endif # !simulator
diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk
index e53378d..315acdb 100644
--- a/cmds/installd/tests/Android.mk
+++ b/cmds/installd/tests/Android.mk
@@ -2,8 +2,6 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 # Build the unit tests.
 test_src_files := \
     installd_utils_test.cpp
@@ -38,5 +36,3 @@
     $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
     $(eval include $(BUILD_EXECUTABLE)) \
 )
-
-endif
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 67dd9f8..5a9b979 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -14,8 +14,6 @@
 # limitations under the License.
 #
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -32,5 +30,3 @@
 LOCAL_MODULE:= keystore_cli
 LOCAL_MODULE_TAGS := debug
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/rawbu/Android.mk b/cmds/rawbu/Android.mk
index c1be8a4..b580390 100644
--- a/cmds/rawbu/Android.mk
+++ b/cmds/rawbu/Android.mk
@@ -1,7 +1,5 @@
 # Copyright 2009 The Android Open Source Project
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -15,5 +13,3 @@
 LOCAL_MODULE_TAGS := debug
 
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/screenshot/Android.mk b/cmds/screenshot/Android.mk
index 99c7aeb..73a8e22 100644
--- a/cmds/screenshot/Android.mk
+++ b/cmds/screenshot/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -12,5 +10,3 @@
 LOCAL_C_INCLUDES += external/zlib
 
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
index fe5929b..ea80c7d 100644
--- a/cmds/servicemanager/Android.mk
+++ b/cmds/servicemanager/Android.mk
@@ -1,4 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
 LOCAL_PATH:= $(call my-dir)
 
 #include $(CLEAR_VARS)
@@ -14,4 +13,3 @@
     LOCAL_CFLAGS += -DLVMX
 endif
 include $(BUILD_EXECUTABLE)
-endif
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index d77dbdc..e6c2a0f 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -87,11 +87,13 @@
     private AnimatorSetListener mSetListener = null;
 
     /**
-     * Flag indicating that the AnimatorSet has been canceled (by calling cancel() or end()).
+     * Flag indicating that the AnimatorSet has been manually
+     * terminated (by calling cancel() or end()).
      * This flag is used to avoid starting other animations when currently-playing
-     * child animations of this AnimatorSet end.
+     * child animations of this AnimatorSet end. It also determines whether cancel/end
+     * notifications are sent out via the normal AnimatorSetListener mechanism.
      */
-    boolean mCanceled = false;
+    boolean mTerminated = false;
 
     // The amount of time in ms to delay starting the animation after start() is called
     private long mStartDelay = 0;
@@ -271,31 +273,29 @@
     @SuppressWarnings("unchecked")
     @Override
     public void cancel() {
-        mCanceled = true;
-        if (mListeners != null) {
-            ArrayList<AnimatorListener> tmpListeners =
-                    (ArrayList<AnimatorListener>) mListeners.clone();
-            for (AnimatorListener listener : tmpListeners) {
-                listener.onAnimationCancel(this);
-            }
-        }
-        if (mDelayAnim != null && mDelayAnim.isRunning()) {
-            // If we're currently in the startDelay period, just cancel that animator and
-            // send out the end event to all listeners
-            mDelayAnim.cancel();
+        mTerminated = true;
+        if (isRunning()) {
+            ArrayList<AnimatorListener> tmpListeners = null;
             if (mListeners != null) {
-                ArrayList<AnimatorListener> tmpListeners =
-                        (ArrayList<AnimatorListener>) mListeners.clone();
+                tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone();
+                for (AnimatorListener listener : tmpListeners) {
+                    listener.onAnimationCancel(this);
+                }
+            }
+            if (mDelayAnim != null && mDelayAnim.isRunning()) {
+                // If we're currently in the startDelay period, just cancel that animator and
+                // send out the end event to all listeners
+                mDelayAnim.cancel();
+            } else  if (mSortedNodes.size() > 0) {
+                for (Node node : mSortedNodes) {
+                    node.animation.cancel();
+                }
+            }
+            if (tmpListeners != null) {
                 for (AnimatorListener listener : tmpListeners) {
                     listener.onAnimationEnd(this);
                 }
             }
-            return;
-        }
-        if (mSortedNodes.size() > 0) {
-            for (Node node : mSortedNodes) {
-                node.animation.cancel();
-            }
         }
     }
 
@@ -307,23 +307,32 @@
      */
     @Override
     public void end() {
-        mCanceled = true;
-        if (mSortedNodes.size() != mNodes.size()) {
-            // hasn't been started yet - sort the nodes now, then end them
-            sortNodes();
-            for (Node node : mSortedNodes) {
-                if (mSetListener == null) {
-                    mSetListener = new AnimatorSetListener(this);
+        mTerminated = true;
+        if (isRunning()) {
+            if (mSortedNodes.size() != mNodes.size()) {
+                // hasn't been started yet - sort the nodes now, then end them
+                sortNodes();
+                for (Node node : mSortedNodes) {
+                    if (mSetListener == null) {
+                        mSetListener = new AnimatorSetListener(this);
+                    }
+                    node.animation.addListener(mSetListener);
                 }
-                node.animation.addListener(mSetListener);
             }
-        }
-        if (mDelayAnim != null) {
-            mDelayAnim.cancel();
-        }
-        if (mSortedNodes.size() > 0) {
-            for (Node node : mSortedNodes) {
-                node.animation.end();
+            if (mDelayAnim != null) {
+                mDelayAnim.cancel();
+            }
+            if (mSortedNodes.size() > 0) {
+                for (Node node : mSortedNodes) {
+                    node.animation.end();
+                }
+            }
+            if (mListeners != null) {
+                ArrayList<AnimatorListener> tmpListeners =
+                        (ArrayList<AnimatorListener>) mListeners.clone();
+                for (AnimatorListener listener : tmpListeners) {
+                    listener.onAnimationEnd(this);
+                }
             }
         }
     }
@@ -424,7 +433,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public void start() {
-        mCanceled = false;
+        mTerminated = false;
 
         // First, sort the nodes (if necessary). This will ensure that sortedNodes
         // contains the animation nodes in the correct order.
@@ -437,7 +446,8 @@
             ArrayList<AnimatorListener> oldListeners = node.animation.getListeners();
             if (oldListeners != null && oldListeners.size() > 0) {
                 for (AnimatorListener listener : oldListeners) {
-                    if (listener instanceof DependencyListener) {
+                    if (listener instanceof DependencyListener ||
+                            listener instanceof AnimatorSetListener) {
                         node.animation.removeListener(listener);
                     }
                 }
@@ -522,7 +532,7 @@
          * and will populate any appropriate lists, when it is started.
          */
         anim.mNeedsSort = true;
-        anim.mCanceled = false;
+        anim.mTerminated = false;
         anim.mPlayingSet = new ArrayList<Animator>();
         anim.mNodeMap = new HashMap<Animator, Node>();
         anim.mNodes = new ArrayList<Node>();
@@ -640,7 +650,7 @@
          * @param dependencyAnimation the animation that sent the event.
          */
         private void startIfReady(Animator dependencyAnimation) {
-            if (mAnimatorSet.mCanceled) {
+            if (mAnimatorSet.mTerminated) {
                 // if the parent AnimatorSet was canceled, then don't start any dependent anims
                 return;
             }
@@ -676,11 +686,15 @@
         }
 
         public void onAnimationCancel(Animator animation) {
-            if (mPlayingSet.size() == 0) {
-                if (mListeners != null) {
-                    int numListeners = mListeners.size();
-                    for (int i = 0; i < numListeners; ++i) {
-                        mListeners.get(i).onAnimationCancel(mAnimatorSet);
+            if (!mTerminated) {
+                // Listeners are already notified of the AnimatorSet canceling in cancel().
+                // The logic below only kicks in when animations end normally
+                if (mPlayingSet.size() == 0) {
+                    if (mListeners != null) {
+                        int numListeners = mListeners.size();
+                        for (int i = 0; i < numListeners; ++i) {
+                            mListeners.get(i).onAnimationCancel(mAnimatorSet);
+                        }
                     }
                 }
             }
@@ -692,24 +706,28 @@
             mPlayingSet.remove(animation);
             Node animNode = mAnimatorSet.mNodeMap.get(animation);
             animNode.done = true;
-            ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes;
-            boolean allDone = true;
-            int numSortedNodes = sortedNodes.size();
-            for (int i = 0; i < numSortedNodes; ++i) {
-                if (!sortedNodes.get(i).done) {
-                    allDone = false;
-                    break;
+            if (!mTerminated) {
+                // Listeners are already notified of the AnimatorSet ending in cancel() or
+                // end(); the logic below only kicks in when animations end normally
+                ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes;
+                boolean allDone = true;
+                int numSortedNodes = sortedNodes.size();
+                for (int i = 0; i < numSortedNodes; ++i) {
+                    if (!sortedNodes.get(i).done) {
+                        allDone = false;
+                        break;
+                    }
                 }
-            }
-            if (allDone) {
-                // If this was the last child animation to end, then notify listeners that this
-                // AnimatorSet has ended
-                if (mListeners != null) {
-                    ArrayList<AnimatorListener> tmpListeners =
-                            (ArrayList<AnimatorListener>) mListeners.clone();
-                    int numListeners = tmpListeners.size();
-                    for (int i = 0; i < numListeners; ++i) {
-                        tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
+                if (allDone) {
+                    // If this was the last child animation to end, then notify listeners that this
+                    // AnimatorSet has ended
+                    if (mListeners != null) {
+                        ArrayList<AnimatorListener> tmpListeners =
+                                (ArrayList<AnimatorListener>) mListeners.clone();
+                        int numListeners = tmpListeners.size();
+                        for (int i = 0; i < numListeners; ++i) {
+                            tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
+                        }
                     }
                 }
             }
@@ -791,6 +809,8 @@
                         }
                     }
                 }
+                // nodes are 'done' by default; they become un-done when started, and done
+                // again when ended
                 node.done = false;
             }
         }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 1dcaa04..90d676e 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -933,17 +933,17 @@
 
     @Override
     public void cancel() {
-        if (mListeners != null) {
-            ArrayList<AnimatorListener> tmpListeners =
-                    (ArrayList<AnimatorListener>) mListeners.clone();
-            for (AnimatorListener listener : tmpListeners) {
-                listener.onAnimationCancel(this);
-            }
-        }
         // Only cancel if the animation is actually running or has been started and is about
         // to run
         if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
                 sDelayedAnims.get().contains(this)) {
+            if (mListeners != null) {
+                ArrayList<AnimatorListener> tmpListeners =
+                        (ArrayList<AnimatorListener>) mListeners.clone();
+                for (AnimatorListener listener : tmpListeners) {
+                    listener.onAnimationCancel(this);
+                }
+            }
             endAnimation();
         }
     }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a6658cc..d207a0a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1471,6 +1471,24 @@
     }
 
     /**
+     * Returns the usage statistics of each installed package.
+     *
+     * @hide
+     */
+    public PkgUsageStats[] getAllPackageUsageStats() {
+        try {
+            IUsageStats usageStatsService = IUsageStats.Stub.asInterface(
+                    ServiceManager.getService("usagestats"));
+            if (usageStatsService != null) {
+                return usageStatsService.getAllPkgUsageStats();
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Could not query usage stats", e);
+        }
+        return new PkgUsageStats[0];
+    }
+
+    /**
      * @param userid the user's id. Zero indicates the default user 
      * @hide
      */
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 9d40c42..fbff7d8 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -47,13 +47,39 @@
      * {@link SystemClock#elapsedRealtime()} timestamp when this data was
      * generated.
      */
-    public final long elapsedRealtime;
-    public int size;
-    public String[] iface;
-    public int[] uid;
-    public int[] tag;
-    public long[] rx;
-    public long[] tx;
+    private final long elapsedRealtime;
+    private int size;
+    private String[] iface;
+    private int[] uid;
+    private int[] tag;
+    private long[] rxBytes;
+    private long[] rxPackets;
+    private long[] txBytes;
+    private long[] txPackets;
+
+    public static class Entry {
+        public String iface;
+        public int uid;
+        public int tag;
+        public long rxBytes;
+        public long rxPackets;
+        public long txBytes;
+        public long txPackets;
+
+        public Entry() {
+        }
+
+        public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes,
+                long txPackets) {
+            this.iface = iface;
+            this.uid = uid;
+            this.tag = tag;
+            this.rxBytes = rxBytes;
+            this.rxPackets = rxPackets;
+            this.txBytes = txBytes;
+            this.txPackets = txPackets;
+        }
+    }
 
     public NetworkStats(long elapsedRealtime, int initialSize) {
         this.elapsedRealtime = elapsedRealtime;
@@ -61,8 +87,10 @@
         this.iface = new String[initialSize];
         this.uid = new int[initialSize];
         this.tag = new int[initialSize];
-        this.rx = new long[initialSize];
-        this.tx = new long[initialSize];
+        this.rxBytes = new long[initialSize];
+        this.rxPackets = new long[initialSize];
+        this.txBytes = new long[initialSize];
+        this.txPackets = new long[initialSize];
     }
 
     public NetworkStats(Parcel parcel) {
@@ -71,46 +99,93 @@
         iface = parcel.createStringArray();
         uid = parcel.createIntArray();
         tag = parcel.createIntArray();
-        rx = parcel.createLongArray();
-        tx = parcel.createLongArray();
+        rxBytes = parcel.createLongArray();
+        rxPackets = parcel.createLongArray();
+        txBytes = parcel.createLongArray();
+        txPackets = parcel.createLongArray();
+    }
+
+    public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
+            long txBytes, long txPackets) {
+        return addValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets));
     }
 
     /**
-     * Add new stats entry with given values.
+     * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
+     * object can be recycled across multiple calls.
      */
-    public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) {
+    public NetworkStats addValues(Entry entry) {
         if (size >= this.iface.length) {
-            final int newLength = Math.max(this.iface.length, 10) * 3 / 2;
-            this.iface = Arrays.copyOf(this.iface, newLength);
-            this.uid = Arrays.copyOf(this.uid, newLength);
-            this.tag = Arrays.copyOf(this.tag, newLength);
-            this.rx = Arrays.copyOf(this.rx, newLength);
-            this.tx = Arrays.copyOf(this.tx, newLength);
+            final int newLength = Math.max(iface.length, 10) * 3 / 2;
+            iface = Arrays.copyOf(iface, newLength);
+            uid = Arrays.copyOf(uid, newLength);
+            tag = Arrays.copyOf(tag, newLength);
+            rxBytes = Arrays.copyOf(rxBytes, newLength);
+            rxPackets = Arrays.copyOf(rxPackets, newLength);
+            txBytes = Arrays.copyOf(txBytes, newLength);
+            txPackets = Arrays.copyOf(txPackets, newLength);
         }
 
-        this.iface[size] = iface;
-        this.uid[size] = uid;
-        this.tag[size] = tag;
-        this.rx[size] = rx;
-        this.tx[size] = tx;
+        iface[size] = entry.iface;
+        uid[size] = entry.uid;
+        tag[size] = entry.tag;
+        rxBytes[size] = entry.rxBytes;
+        rxPackets[size] = entry.rxPackets;
+        txBytes[size] = entry.txBytes;
+        txPackets[size] = entry.txPackets;
         size++;
 
         return this;
     }
 
     /**
+     * Return specific stats entry.
+     */
+    public Entry getValues(int i, Entry recycle) {
+        final Entry entry = recycle != null ? recycle : new Entry();
+        entry.iface = iface[i];
+        entry.uid = uid[i];
+        entry.tag = tag[i];
+        entry.rxBytes = rxBytes[i];
+        entry.rxPackets = rxPackets[i];
+        entry.txBytes = txBytes[i];
+        entry.txPackets = txPackets[i];
+        return entry;
+    }
+
+    public long getElapsedRealtime() {
+        return elapsedRealtime;
+    }
+
+    public int size() {
+        return size;
+    }
+
+    // @VisibleForTesting
+    public int internalSize() {
+        return iface.length;
+    }
+
+    public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
+            long txBytes, long txPackets) {
+        return combineValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets));
+    }
+
+    /**
      * Combine given values with an existing row, or create a new row if
      * {@link #findIndex(String, int, int)} is unable to find match. Can also be
      * used to subtract values from existing rows.
      */
-    public NetworkStats combineEntry(String iface, int uid, int tag, long rx, long tx) {
-        final int i = findIndex(iface, uid, tag);
+    public NetworkStats combineValues(Entry entry) {
+        final int i = findIndex(entry.iface, entry.uid, entry.tag);
         if (i == -1) {
             // only create new entry when positive contribution
-            addEntry(iface, uid, tag, rx, tx);
+            addValues(entry);
         } else {
-            this.rx[i] += rx;
-            this.tx[i] += tx;
+            rxBytes[i] += entry.rxBytes;
+            rxPackets[i] += entry.rxPackets;
+            txBytes[i] += entry.txBytes;
+            txPackets[i] += entry.txPackets;
         }
         return this;
     }
@@ -199,30 +274,41 @@
         }
 
         // result will have our rows, and elapsed time between snapshots
+        final Entry entry = new Entry();
         final NetworkStats result = new NetworkStats(deltaRealtime, size);
         for (int i = 0; i < size; i++) {
-            final String iface = this.iface[i];
-            final int uid = this.uid[i];
-            final int tag = this.tag[i];
+            entry.iface = iface[i];
+            entry.uid = uid[i];
+            entry.tag = tag[i];
 
             // find remote row that matches, and subtract
-            final int j = value.findIndex(iface, uid, tag);
+            final int j = value.findIndex(entry.iface, entry.uid, entry.tag);
             if (j == -1) {
                 // newly appearing row, return entire value
-                result.addEntry(iface, uid, tag, this.rx[i], this.tx[i]);
+                entry.rxBytes = rxBytes[i];
+                entry.rxPackets = rxPackets[i];
+                entry.txBytes = txBytes[i];
+                entry.txPackets = txPackets[i];
             } else {
                 // existing row, subtract remote value
-                long rx = this.rx[i] - value.rx[j];
-                long tx = this.tx[i] - value.tx[j];
-                if (enforceMonotonic && (rx < 0 || tx < 0)) {
+                entry.rxBytes = rxBytes[i] - value.rxBytes[j];
+                entry.rxPackets = rxPackets[i] - value.rxPackets[j];
+                entry.txBytes = txBytes[i] - value.txBytes[j];
+                entry.txPackets = txPackets[i] - value.txPackets[j];
+                if (enforceMonotonic
+                        && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
+                                || entry.txPackets < 0)) {
                     throw new IllegalArgumentException("found non-monotonic values");
                 }
                 if (clampNegative) {
-                    rx = Math.max(0, rx);
-                    tx = Math.max(0, tx);
+                    entry.rxBytes = Math.max(0, entry.rxBytes);
+                    entry.rxPackets = Math.max(0, entry.rxPackets);
+                    entry.txBytes = Math.max(0, entry.txBytes);
+                    entry.txPackets = Math.max(0, entry.txPackets);
                 }
-                result.addEntry(iface, uid, tag, rx, tx);
             }
+
+            result.addValues(entry);
         }
 
         return result;
@@ -235,13 +321,15 @@
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix);
         pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
-        for (int i = 0; i < iface.length; i++) {
+        for (int i = 0; i < size; i++) {
             pw.print(prefix);
             pw.print("  iface="); pw.print(iface[i]);
             pw.print(" uid="); pw.print(uid[i]);
             pw.print(" tag="); pw.print(tag[i]);
-            pw.print(" rx="); pw.print(rx[i]);
-            pw.print(" tx="); pw.println(tx[i]);
+            pw.print(" rxBytes="); pw.print(rxBytes[i]);
+            pw.print(" rxPackets="); pw.print(rxPackets[i]);
+            pw.print(" txBytes="); pw.print(txBytes[i]);
+            pw.print(" txPackets="); pw.println(txPackets[i]);
         }
     }
 
@@ -264,8 +352,10 @@
         dest.writeStringArray(iface);
         dest.writeIntArray(uid);
         dest.writeIntArray(tag);
-        dest.writeLongArray(rx);
-        dest.writeLongArray(tx);
+        dest.writeLongArray(rxBytes);
+        dest.writeLongArray(rxPackets);
+        dest.writeLongArray(txBytes);
+        dest.writeLongArray(txPackets);
     }
 
     public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index dd2945c..8bd1738 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -43,13 +43,20 @@
     private static final int VERSION_INIT = 1;
 
     // TODO: teach about varint encoding to use less disk space
+    // TODO: extend to record rxPackets/txPackets
 
-    public final long bucketDuration;
+    private final long bucketDuration;
+    private int bucketCount;
+    private long[] bucketStart;
+    private long[] rxBytes;
+    private long[] txBytes;
 
-    public int bucketCount;
-    public long[] bucketStart;
-    public long[] rx;
-    public long[] tx;
+    public static class Entry {
+        public long bucketStart;
+        public long bucketDuration;
+        public long rxBytes;
+        public long txBytes;
+    }
 
     public NetworkStatsHistory(long bucketDuration) {
         this(bucketDuration, 10);
@@ -58,16 +65,16 @@
     public NetworkStatsHistory(long bucketDuration, int initialSize) {
         this.bucketDuration = bucketDuration;
         bucketStart = new long[initialSize];
-        rx = new long[initialSize];
-        tx = new long[initialSize];
+        rxBytes = new long[initialSize];
+        txBytes = new long[initialSize];
         bucketCount = 0;
     }
 
     public NetworkStatsHistory(Parcel in) {
         bucketDuration = in.readLong();
         bucketStart = readLongArray(in);
-        rx = in.createLongArray();
-        tx = in.createLongArray();
+        rxBytes = in.createLongArray();
+        txBytes = in.createLongArray();
         bucketCount = bucketStart.length;
     }
 
@@ -75,8 +82,8 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(bucketDuration);
         writeLongArray(out, bucketStart, bucketCount);
-        writeLongArray(out, rx, bucketCount);
-        writeLongArray(out, tx, bucketCount);
+        writeLongArray(out, rxBytes, bucketCount);
+        writeLongArray(out, txBytes, bucketCount);
     }
 
     public NetworkStatsHistory(DataInputStream in) throws IOException {
@@ -85,8 +92,8 @@
             case VERSION_INIT: {
                 bucketDuration = in.readLong();
                 bucketStart = readLongArray(in);
-                rx = readLongArray(in);
-                tx = readLongArray(in);
+                rxBytes = readLongArray(in);
+                txBytes = readLongArray(in);
                 bucketCount = bucketStart.length;
                 break;
             }
@@ -100,8 +107,8 @@
         out.writeInt(VERSION_INIT);
         out.writeLong(bucketDuration);
         writeLongArray(out, bucketStart, bucketCount);
-        writeLongArray(out, rx, bucketCount);
-        writeLongArray(out, tx, bucketCount);
+        writeLongArray(out, rxBytes, bucketCount);
+        writeLongArray(out, txBytes, bucketCount);
     }
 
     /** {@inheritDoc} */
@@ -109,6 +116,42 @@
         return 0;
     }
 
+    public int size() {
+        return bucketCount;
+    }
+
+    public long getBucketDuration() {
+        return bucketDuration;
+    }
+
+    public long getStart() {
+        if (bucketCount > 0) {
+            return bucketStart[0];
+        } else {
+            return Long.MAX_VALUE;
+        }
+    }
+
+    public long getEnd() {
+        if (bucketCount > 0) {
+            return bucketStart[bucketCount - 1] + bucketDuration;
+        } else {
+            return Long.MIN_VALUE;
+        }
+    }
+
+    /**
+     * Return specific stats entry.
+     */
+    public Entry getValues(int i, Entry recycle) {
+        final Entry entry = recycle != null ? recycle : new Entry();
+        entry.bucketStart = bucketStart[i];
+        entry.bucketDuration = bucketDuration;
+        entry.rxBytes = rxBytes[i];
+        entry.txBytes = txBytes[i];
+        return entry;
+    }
+
     /**
      * Record that data traffic occurred in the given time range. Will
      * distribute across internal buckets, creating new buckets as needed.
@@ -135,8 +178,8 @@
 
             final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
             if (overlap > 0) {
-                this.rx[i] += rx * overlap / duration;
-                this.tx[i] += tx * overlap / duration;
+                this.rxBytes[i] += rx * overlap / duration;
+                this.txBytes[i] += tx * overlap / duration;
             }
         }
     }
@@ -149,7 +192,7 @@
         for (int i = 0; i < input.bucketCount; i++) {
             final long start = input.bucketStart[i];
             final long end = start + input.bucketDuration;
-            recordData(start, end, input.rx[i], input.tx[i]);
+            recordData(start, end, input.rxBytes[i], input.txBytes[i]);
         }
     }
 
@@ -179,8 +222,8 @@
         if (bucketCount >= bucketStart.length) {
             final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
             bucketStart = Arrays.copyOf(bucketStart, newLength);
-            rx = Arrays.copyOf(rx, newLength);
-            tx = Arrays.copyOf(tx, newLength);
+            rxBytes = Arrays.copyOf(rxBytes, newLength);
+            txBytes = Arrays.copyOf(txBytes, newLength);
         }
 
         // create gap when inserting bucket in middle
@@ -189,13 +232,13 @@
             final int length = bucketCount - index;
 
             System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
-            System.arraycopy(rx, index, rx, dstPos, length);
-            System.arraycopy(tx, index, tx, dstPos, length);
+            System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
+            System.arraycopy(txBytes, index, txBytes, dstPos, length);
         }
 
         bucketStart[index] = start;
-        rx[index] = 0;
-        tx[index] = 0;
+        rxBytes[index] = 0;
+        txBytes[index] = 0;
         bucketCount++;
     }
 
@@ -216,8 +259,8 @@
         if (i > 0) {
             final int length = bucketStart.length;
             bucketStart = Arrays.copyOfRange(bucketStart, i, length);
-            rx = Arrays.copyOfRange(rx, i, length);
-            tx = Arrays.copyOfRange(tx, i, length);
+            rxBytes = Arrays.copyOfRange(rxBytes, i, length);
+            txBytes = Arrays.copyOfRange(txBytes, i, length);
             bucketCount -= i;
         }
     }
@@ -226,9 +269,20 @@
      * Return interpolated data usage across the requested range. Interpolates
      * across buckets, so values may be rounded slightly.
      */
-    public long[] getTotalData(long start, long end, long[] outTotal) {
-        long rx = 0;
-        long tx = 0;
+    public Entry getValues(long start, long end, Entry recycle) {
+        return getValues(start, end, Long.MAX_VALUE, recycle);
+    }
+
+    /**
+     * Return interpolated data usage across the requested range. Interpolates
+     * across buckets, so values may be rounded slightly.
+     */
+    public Entry getValues(long start, long end, long now, Entry recycle) {
+        final Entry entry = recycle != null ? recycle : new Entry();
+        entry.bucketStart = start;
+        entry.bucketDuration = end - start;
+        entry.rxBytes = 0;
+        entry.txBytes = 0;
 
         for (int i = bucketCount - 1; i >= 0; i--) {
             final long curStart = bucketStart[i];
@@ -239,19 +293,19 @@
             // bucket is newer than record; keep looking
             if (curStart > end) continue;
 
+            // include full value for active buckets, otherwise only fractional
+            final boolean activeBucket = curStart < now && curEnd > now;
             final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
-            if (overlap > 0) {
-                rx += this.rx[i] * overlap / bucketDuration;
-                tx += this.tx[i] * overlap / bucketDuration;
+            if (activeBucket || overlap == bucketDuration) {
+                entry.rxBytes += rxBytes[i];
+                entry.txBytes += txBytes[i];
+            } else if (overlap > 0) {
+                entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
+                entry.txBytes += txBytes[i] * overlap / bucketDuration;
             }
         }
 
-        if (outTotal == null || outTotal.length != 2) {
-            outTotal = new long[2];
-        }
-        outTotal[0] = rx;
-        outTotal[1] = tx;
-        return outTotal;
+        return entry;
     }
 
     /**
@@ -292,8 +346,8 @@
         for (int i = start; i < bucketCount; i++) {
             pw.print(prefix);
             pw.print("  bucketStart="); pw.print(bucketStart[i]);
-            pw.print(" rx="); pw.print(rx[i]);
-            pw.print(" tx="); pw.println(tx[i]);
+            pw.print(" rxBytes="); pw.print(rxBytes[i]);
+            pw.print(" txBytes="); pw.println(txBytes[i]);
         }
     }
 
diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java
index 641a576..c534e58 100644
--- a/core/java/android/net/http/AndroidHttpClient.java
+++ b/core/java/android/net/http/AndroidHttpClient.java
@@ -65,7 +65,7 @@
 import android.util.Log;
 
 /**
- * Subclass of the Apache {@link DefaultHttpClient} that is configured with
+ * Implementation of the Apache {@link DefaultHttpClient} that is configured with
  * reasonable default settings and registered schemes for Android, and
  * also lets the user add {@link HttpRequestInterceptor} classes.
  * Don't create this directly, use the {@link #newInstance} factory method.
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 269e50e..5b1f563 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -270,13 +270,12 @@
      * @param targetSdkVersion The target SDK version for the app.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
-     * @return int If > 0 the pid of the new process; if 0 the process is
-     *         being emulated by a thread
+     * @return An object that describes the result of the attempt to start the process.
      * @throws RuntimeException on fatal start failure
      * 
      * {@hide}
      */
-    public static final int start(final String processClass,
+    public static final ProcessStartResult start(final String processClass,
                                   final String niceName,
                                   int uid, int gid, int[] gids,
                                   int debugFlags, int targetSdkVersion,
@@ -376,14 +375,11 @@
      * and returns the child's pid. Please note: the present implementation
      * replaces newlines in the argument list with spaces.
      * @param args argument list
-     * @return PID of new child process
+     * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
      */
-    private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
+    private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
             throws ZygoteStartFailedEx {
-
-        int pid;
-
         openZygoteSocketIfNeeded();
 
         try {
@@ -394,7 +390,8 @@
              * b) a number of newline-separated argument strings equal to count
              *
              * After the zygote process reads these it will write the pid of
-             * the child or -1 on failure.
+             * the child or -1 on failure, followed by boolean to
+             * indicate whether a wrapper process was used.
              */
 
             sZygoteWriter.write(Integer.toString(args.size()));
@@ -414,11 +411,13 @@
             sZygoteWriter.flush();
 
             // Should there be a timeout on this?
-            pid = sZygoteInputStream.readInt();
-
-            if (pid < 0) {
+            ProcessStartResult result = new ProcessStartResult();
+            result.pid = sZygoteInputStream.readInt();
+            if (result.pid < 0) {
                 throw new ZygoteStartFailedEx("fork() failed");
             }
+            result.usingWrapper = sZygoteInputStream.readBoolean();
+            return result;
         } catch (IOException ex) {
             try {
                 if (sZygoteSocket != null) {
@@ -433,8 +432,6 @@
 
             throw new ZygoteStartFailedEx(ex);
         }
-
-        return pid;
     }
 
     /**
@@ -449,18 +446,16 @@
      * @param debugFlags Additional flags.
      * @param targetSdkVersion The target SDK version for the app.
      * @param extraArgs Additional arguments to supply to the zygote process.
-     * @return PID
+     * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
      */
-    private static int startViaZygote(final String processClass,
+    private static ProcessStartResult startViaZygote(final String processClass,
                                   final String niceName,
                                   final int uid, final int gid,
                                   final int[] gids,
                                   int debugFlags, int targetSdkVersion,
                                   String[] extraArgs)
                                   throws ZygoteStartFailedEx {
-        int pid;
-
         synchronized(Process.class) {
             ArrayList<String> argsForZygote = new ArrayList<String>();
 
@@ -516,15 +511,9 @@
                     argsForZygote.add(arg);
                 }
             }
-            
-            pid = zygoteSendArgsAndGetPid(argsForZygote);
-        }
 
-        if (pid <= 0) {
-            throw new ZygoteStartFailedEx("zygote start failed:" + pid);
+            return zygoteSendArgsAndGetResult(argsForZygote);
         }
-
-        return pid;
     }
     
     /**
@@ -808,4 +797,21 @@
      * @hide
      */
     public static final native long getPss(int pid);
+
+    /**
+     * Specifies the outcome of having started a process.
+     * @hide
+     */
+    public static final class ProcessStartResult {
+        /**
+         * The PID of the newly started process.
+         * Always >= 0.  (If the start failed, an exception will have been thrown instead.)
+         */
+        public int pid;
+
+        /**
+         * True if the process was started with a wrapper attached.
+         */
+        public boolean usingWrapper;
+    }
 }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 61deea4..ec67683 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -135,14 +135,6 @@
     public static final String ALLOW_PROFILE = "allow_profile";
 
     /**
-     * A query parameter key used to specify the package that is requesting a query.
-     * This is used for restricting data based on package name.
-     *
-     * @hide
-     */
-    public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package";
-
-    /**
      * Query parameter that should be used by the client to access a specific
      * {@link Directory}. The parameter value should be the _ID of the corresponding
      * directory, e.g.
@@ -271,8 +263,6 @@
      * <li>The URI authority is replaced with the corresponding {@link #DIRECTORY_AUTHORITY}.</li>
      * <li>The {@code accountName=} and {@code accountType=} parameters are added or
      * replaced using the corresponding {@link #ACCOUNT_TYPE} and {@link #ACCOUNT_NAME} values.</li>
-     * <li>If the URI is missing a ContactsContract.REQUESTING_PACKAGE_PARAM_KEY
-     * parameter, this parameter is added.</li>
      * </ul>
      * </p>
      * <p>
@@ -1881,13 +1871,16 @@
         public static final String CONTACT_ID = "contact_id";
 
         /**
-         * Flag indicating that this {@link RawContacts} entry and its children have
-         * been restricted to specific platform apps.
-         * <P>Type: INTEGER (boolean)</P>
+         * The data set within the account that this row belongs to.  This allows
+         * multiple sync adapters for the same account type to distinguish between
+         * each others' data.
          *
-         * @hide until finalized in future platform release
+         * This is empty by default, and is completely optional.  It only needs to
+         * be populated if multiple sync adapters are entering distinct data for
+         * the same account type and account name.
+         * <P>Type: TEXT</P>
          */
-        public static final String IS_RESTRICTED = "is_restricted";
+        public static final String DATA_SET = "data_set";
 
         /**
          * The aggregation mode for this contact.
@@ -2211,8 +2204,8 @@
      * <td>The name of the account instance to which this row belongs, which when paired with
      * {@link #ACCOUNT_TYPE} identifies a specific account.
      * For example, this will be the Gmail address if it is a Google account.
-     * It should be set at the time
-     * the raw contact is inserted and never changed afterwards.</td>
+     * It should be set at the time the raw contact is inserted and never
+     * changed afterwards.</td>
      * </tr>
      * <tr>
      * <td>String</td>
@@ -2222,8 +2215,8 @@
      * <p>
      * The type of account to which this row belongs, which when paired with
      * {@link #ACCOUNT_NAME} identifies a specific account.
-     * It should be set at the time
-     * the raw contact is inserted and never changed afterwards.
+     * It should be set at the time the raw contact is inserted and never
+     * changed afterwards.
      * </p>
      * <p>
      * To ensure uniqueness, new account types should be chosen according to the
@@ -2233,15 +2226,38 @@
      * </tr>
      * <tr>
      * <td>String</td>
+     * <td>{@link #DATA_SET}</td>
+     * <td>read/write-once</td>
+     * <td>
+     * <p>
+     * The data set within the account that this row belongs to.  This allows
+     * multiple sync adapters for the same account type to distinguish between
+     * each others' data.  The combination of {@link #ACCOUNT_TYPE},
+     * {@link #ACCOUNT_NAME}, and {@link #DATA_SET} identifies a set of data
+     * that is associated with a single sync adapter.
+     * </p>
+     * <p>
+     * This is empty by default, and is completely optional.  It only needs to
+     * be populated if multiple sync adapters are entering distinct data for
+     * the same account type and account name.
+     * </p>
+     * <p>
+     * It should be set at the time the raw contact is inserted and never
+     * changed afterwards.
+     * </p>
+     * </td>
+     * </tr>
+     * <tr>
+     * <td>String</td>
      * <td>{@link #SOURCE_ID}</td>
      * <td>read/write</td>
      * <td>String that uniquely identifies this row to its source account.
      * Typically it is set at the time the raw contact is inserted and never
      * changed afterwards. The one notable exception is a new raw contact: it
-     * will have an account name and type, but no source id. This
-     * indicates to the sync adapter that a new contact needs to be created
-     * server-side and its ID stored in the corresponding SOURCE_ID field on
-     * the phone.
+     * will have an account name and type (and possibly a data set), but no
+     * source id. This indicates to the sync adapter that a new contact needs
+     * to be created server-side and its ID stored in the corresponding
+     * SOURCE_ID field on the phone.
      * </td>
      * </tr>
      * <tr>
@@ -2537,7 +2553,6 @@
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED);
-                DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, IS_RESTRICTED);
                 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, NAME_VERIFIED);
                 android.content.Entity contact = new android.content.Entity(cv);
 
@@ -3814,27 +3829,6 @@
 
         /**
          * <p>
-         * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward
-         * Data.CONTENT_URI contains only exportable data.
-         * </p>
-         * <p>
-         * This flag is useful (currently) only for vCard exporter in Contacts app, which
-         * needs to exclude "un-exportable" data from available data to export, while
-         * Contacts app itself has priviledge to access all data including "un-exportable"
-         * ones and providers return all of them regardless of the callers' intention.
-         * </p>
-         * <p>
-         * Type: INTEGER
-         * </p>
-         *
-         * @hide Maybe available only in Eclair and not really ready for public use.
-         * TODO: remove, or implement this feature completely. As of now (Eclair),
-         * we only use this flag in queryEntities(), not query().
-         */
-        public static final String FOR_EXPORT_ONLY = "for_export_only";
-
-        /**
-         * <p>
          * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
          * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
          * entry of the given {@link ContactsContract.Data} entry.
@@ -6213,6 +6207,18 @@
      */
     protected interface GroupsColumns {
         /**
+         * The data set within the account that this group belongs to.  This allows
+         * multiple sync adapters for the same account type to distinguish between
+         * each others' group data.
+         *
+         * This is empty by default, and is completely optional.  It only needs to
+         * be populated if multiple sync adapters are entering distinct group data
+         * for the same account type and account name.
+         * <P>Type: TEXT</P>
+         */
+        public static final String DATA_SET = "data_set";
+
+        /**
          * The display title of this group.
          * <p>
          * Type: TEXT
@@ -6338,6 +6344,29 @@
      * In other words, it would be a really bad idea to delete and reinsert a
      * group. A sync adapter should always do an update instead.</td>
      * </tr>
+     # <tr>
+     * <td>String</td>
+     * <td>{@link #DATA_SET}</td>
+     * <td>read/write-once</td>
+     * <td>
+     * <p>
+     * The data set within the account that this group belongs to.  This allows
+     * multiple sync adapters for the same account type to distinguish between
+     * each others' group data.  The combination of {@link #ACCOUNT_TYPE},
+     * {@link #ACCOUNT_NAME}, and {@link #DATA_SET} identifies a set of data
+     * that is associated with a single sync adapter.
+     * </p>
+     * <p>
+     * This is empty by default, and is completely optional.  It only needs to
+     * be populated if multiple sync adapters are entering distinct data for
+     * the same account type and account name.
+     * </p>
+     * <p>
+     * It should be set at the time the group is inserted and never changed
+     * afterwards.
+     * </p>
+     * </td>
+     * </tr>
      * <tr>
      * <td>String</td>
      * <td>{@link #TITLE}</td>
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index b23e3ce..ff16c18 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -2403,6 +2403,7 @@
                     convertToAdapterState(state));
             intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
                     convertToAdapterState(prevState));
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             mContext.sendBroadcast(intent, BLUETOOTH_PERM);
             Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
                     + prevState + " -> " + state);
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 8ef4295..1210941 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -384,7 +384,7 @@
             }
             count += written;
         }
-
+        param.mBytesWritten += count;
         param.mLogger.onPlaybackStart();
     }
 
@@ -396,14 +396,16 @@
         params.mLogger.onWriteData();
     }
 
-    // Flush all remaining data to the audio track, stop it and release
-    // all it's resources.
+    // Wait for the audio track to stop playing, and then release it's resources.
     private void handleSynthesisDone(SynthesisMessageParams params) {
         if (DBG) Log.d(TAG, "handleSynthesisDone()");
         final AudioTrack audioTrack = params.getAudioTrack();
 
         try {
             if (audioTrack != null) {
+                if (DBG) Log.d(TAG, "Waiting for audio track to complete : " +
+                        audioTrack.hashCode());
+                blockUntilDone(params);
                 if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]");
                 // The last call to AudioTrack.write( ) will return only after
                 // all data from the audioTrack has been sent to the mixer, so
@@ -417,6 +419,18 @@
         }
     }
 
+    private static void blockUntilDone(SynthesisMessageParams params) {
+        if (params.mAudioTrack == null || params.mBytesWritten <= 0) {
+            return;
+        }
+
+        final AudioTrack track = params.mAudioTrack;
+        final int bytesPerFrame = getBytesPerFrame(params.mAudioFormat);
+        final int lengthInBytes = params.mBytesWritten;
+
+        blockUntilDone(track, bytesPerFrame, lengthInBytes);
+    }
+
     private void handleSynthesisCompleteDataAvailable(MessageParams msg) {
         final SynthesisMessageParams params = (SynthesisMessageParams) msg;
         if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
@@ -455,13 +469,18 @@
     }
 
 
-    private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame, int length) {
-        int lengthInFrames = length / bytesPerFrame;
+    private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame,
+            int lengthInBytes) {
+        int lengthInFrames = lengthInBytes / bytesPerFrame;
         int currentPosition = 0;
         while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) {
+            if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
+                break;
+            }
+
             long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) /
                     audioTrack.getSampleRate();
-            audioTrack.getPlayState();
+
             if (DBG) Log.d(TAG, "About to sleep for : " + estimatedTimeMs + " ms," +
                     " Playback position : " + currentPosition);
             try {
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index caf02ef..ffe70e2 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -32,7 +32,9 @@
     final float mPan;
     final EventLogger mLogger;
 
-    public volatile AudioTrack mAudioTrack;
+    volatile AudioTrack mAudioTrack;
+    // Not volatile, accessed only from the synthesis thread.
+    int mBytesWritten;
 
     private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
 
@@ -52,6 +54,7 @@
 
         // initially null.
         mAudioTrack = null;
+        mBytesWritten = 0;
     }
 
     @Override
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
index 6491da0..47f7358 100644
--- a/core/java/android/view/ActionProvider.java
+++ b/core/java/android/view/ActionProvider.java
@@ -76,7 +76,7 @@
      * Performs an optional default action.
      * <p>
      * For the case of an action provider placed in a menu item not shown as an action this
-     * method is invoked if none of the callbacks for processing menu selection has handled
+     * method is invoked if previous callbacks for processing menu selection has handled
      * the event.
      * </p>
      * <p>
@@ -104,11 +104,36 @@
      * </ul>
      * </p>
      * <p>
-     * The default implementation does not perform any action.
+     * The default implementation does not perform any action and returns false.
      * </p>
-     *
-     * @param actionView A view created by {@link #onCreateActionView()}.
      */
-    public void onPerformDefaultAction(View actionView) {
+    public boolean onPerformDefaultAction() {
+        return false;
+    }
+
+    /**
+     * Determines if this ActionProvider has a submenu associated with it.
+     *
+     * <p>Associated submenus will be shown when an action view is not. This
+     * provider instance will receive a call to {@link #onPrepareSubMenu(SubMenu)}
+     * after the call to {@link #onPerformDefaultAction()} and before a submenu is
+     * displayed to the user.
+     *
+     * @return true if the item backed by this provider should have an associated submenu
+     */
+    public boolean hasSubMenu() {
+        return false;
+    }
+
+    /**
+     * Called to prepare an associated submenu for the menu item backed by this ActionProvider.
+     *
+     * <p>if {@link #hasSubMenu()} returns true, this method will be called when the
+     * menu item is selected to prepare the submenu for presentation to the user. Apps
+     * may use this to create or alter submenu content right before display.
+     *
+     * @param subMenu Submenu that will be displayed
+     */
+    public void onPrepareSubMenu(SubMenu subMenu) {
     }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 1638c74..011e44c 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -128,10 +128,19 @@
     abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
 
     /**
-     * Invoked whenever the size of the target surface changes. This will
-     * not be invoked when the surface is first created.
+     * This method should be invoked whenever the current hardware renderer
+     * context should be reset. 
      */
-    abstract void preapareSurfaceForResize();
+    abstract void invalidate();
+
+    /**
+     * This method should be invoked to ensure the hardware renderer is in
+     * valid state (for instance, to ensure the correct EGL context is bound
+     * to the current thread.)
+     * 
+     * @return true if the renderer is now valid, false otherwise
+     */
+    abstract boolean validate();
 
     /**
      * Setup the hardware renderer for drawing. This is called whenever the
@@ -629,11 +638,16 @@
         }
 
         @Override
-        void preapareSurfaceForResize() {
+        void invalidate() {
             // Cancels any existing buffer to ensure we'll get a buffer
             // of the right size before we call eglSwapBuffers
             sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
-                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);              
+                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+        }
+        
+        @Override
+        boolean validate() {
+            return checkCurrent() != SURFACE_STATE_ERROR;
         }
 
         @Override
@@ -662,7 +676,7 @@
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
 
                 view.mPrivateFlags |= View.DRAWN;
-                
+
                 final int surfaceState = checkCurrent();
                 if (surfaceState != SURFACE_STATE_ERROR) {
                     // We had to change the current surface and/or context, redraw everything
@@ -723,10 +737,21 @@
                 }
             }
         }
-        
+
+        /**
+         * Ensures the currnet EGL context is the one we expect.
+         * 
+         * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
+         *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
+         *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+         */
         private int checkCurrent() {
-            // TODO: Don't check the current context when we have one per UI thread
-            // TODO: Use a threadlocal flag to know whether the surface has changed
+            if (sEglThread != Thread.currentThread()) {
+                throw new IllegalStateException("Hardware acceleration can only be used with a " +
+                        "single UI thread.\nOriginal thread: " + sEglThread + "\n" +
+                        "Current thread: " + Thread.currentThread());
+            }
+
             if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
                     !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
                 if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index a7f0cba..c46e43a 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -166,7 +166,12 @@
                         // Add the item if it hasn't been added (if the item was
                         // a submenu, it would have been added already)
                         if (!menuState.hasAddedItem()) {
-                            menuState.addItem();
+                            if (menuState.itemActionProvider != null &&
+                                    menuState.itemActionProvider.hasSubMenu()) {
+                                menuState.addSubMenuItem();
+                            } else {
+                                menuState.addItem();
+                            }
                         }
                     } else if (tagName.equals(XML_MENU)) {
                         reachedEndOfMenu = true;
@@ -270,6 +275,8 @@
 
         private String itemListenerMethodName;
         
+        private ActionProvider itemActionProvider;
+
         private static final int defaultGroupId = NO_ID;
         private static final int defaultItemId = NO_ID;
         private static final int defaultItemCategory = 0;
@@ -347,6 +354,19 @@
             itemActionViewClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionViewClass);
             itemActionProviderClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionProviderClass);
 
+            final boolean hasActionProvider = itemActionProviderClassName != null;
+            if (hasActionProvider && itemActionViewLayout == 0 && itemActionViewClassName == null) {
+                itemActionProvider = newInstance(itemActionProviderClassName,
+                            ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
+                            mActionProviderConstructorArguments);
+            } else {
+                if (hasActionProvider) {
+                    Log.w(LOG_TAG, "Ignoring attribute 'actionProviderClass'."
+                            + " Action view already specified.");
+                }
+                itemActionProvider = null;
+            }
+
             a.recycle();
 
             itemAdded = false;
@@ -406,16 +426,8 @@
                             + " Action view already specified.");
                 }
             }
-            if (itemActionProviderClassName != null) {
-                if (!actionViewSpecified) {
-                    ActionProvider actionProvider = newInstance(itemActionProviderClassName,
-                            ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
-                            mActionProviderConstructorArguments);
-                    item.setActionProvider(actionProvider);
-                } else {
-                    Log.w(LOG_TAG, "Ignoring attribute 'itemActionProviderClass'."
-                            + " Action view already specified.");
-                }
+            if (itemActionProvider != null) {
+                item.setActionProvider(itemActionProvider);
             }
         }
 
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index b4f323c..1dcbc26 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -901,6 +901,7 @@
                             !mAttachInfo.mTurnOffWindowResizeAnim &&
                             mAttachInfo.mHardwareRenderer != null &&
                             mAttachInfo.mHardwareRenderer.isEnabled() &&
+                            mAttachInfo.mHardwareRenderer.validate() &&
                             lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
 
                         disposeResizeBuffer();
@@ -1314,10 +1315,10 @@
             if (hwInitialized || ((windowShouldResize || params != null) &&
                     mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled())) {
-                if (!hwInitialized) {
-                    mAttachInfo.mHardwareRenderer.preapareSurfaceForResize();
-                }
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
+                if (!hwInitialized) {
+                    mAttachInfo.mHardwareRenderer.invalidate();
+                }
             }
 
             if (!mStopped) {
diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java
index f9d0067d..a1c6a53 100644
--- a/core/java/android/webkit/L10nUtils.java
+++ b/core/java/android/webkit/L10nUtils.java
@@ -75,7 +75,18 @@
         com.android.internal.R.string.autofill_area_code_notext_re,         // IDS_AUTOFILL_AREA_CODE_NOTEXT_RE
         com.android.internal.R.string.autofill_phone_prefix_separator_re,   // IDS_AUTOFILL_PHONE_PREFIX_SEPARATOR_RE
         com.android.internal.R.string.autofill_phone_suffix_separator_re,   // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE
-        com.android.internal.R.string.credit_card_number_preview_format     // IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT
+        com.android.internal.R.string.autofill_province,                    // IDS_AUTOFILL_DIALOG_PROVINCE
+        com.android.internal.R.string.autofill_postal_code,                 // IDS_AUTOFILL_DIALOG_POSTAL_CODE
+        com.android.internal.R.string.autofill_state,                       // IDS_AUTOFILL_DIALOG_STATE
+        com.android.internal.R.string.autofill_zip_code,                    // IDS_AUTOFILL_DIALOG_ZIP_CODE
+        com.android.internal.R.string.autofill_county,                      // IDS_AUTOFILL_DIALOG_COUNTY
+        com.android.internal.R.string.autofill_island,                      // IDS_AUTOFILL_DIALOG_ISLAND
+        com.android.internal.R.string.autofill_district,                    // IDS_AUTOFILL_DIALOG_DISTRICT
+        com.android.internal.R.string.autofill_department,                  // IDS_AUTOFILL_DIALOG_DEPARTMENT
+        com.android.internal.R.string.autofill_prefecture,                  // IDS_AUTOFILL_DIALOG_PREFECTURE
+        com.android.internal.R.string.autofill_parish,                      // IDS_AUTOFILL_DIALOG_PARISH
+        com.android.internal.R.string.autofill_area,                        // IDS_AUTOFILL_DIALOG_AREA
+        com.android.internal.R.string.autofill_emirate                      // IDS_AUTOFILL_DIALOG_EMIRATE
     };
 
     private static Context mApplicationContext;
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index f8c76f2..3b16994 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -21,6 +21,7 @@
 import android.annotation.Widget;
 import android.app.Service;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
 import android.graphics.Canvas;
@@ -239,21 +240,11 @@
     private String[] mDayLabels;
 
     /**
-     * Temporary instance to avoid multiple instantiations.
-     */
-    private Calendar mTempDate = Calendar.getInstance();
-
-    /**
      * The first day of the week.
      */
     private int mFirstDayOfWeek;
 
     /**
-     * The first day of the focused month.
-     */
-    private Calendar mFirstDayOfMonth = Calendar.getInstance();
-
-    /**
      * Which month should be displayed/highlighted [0-11].
      */
     private int mCurrentMonthDisplayed;
@@ -289,14 +280,24 @@
     private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
 
     /**
+     * Temporary instance to avoid multiple instantiations.
+     */
+    private Calendar mTempDate;
+
+    /**
+     * The first day of the focused month.
+     */
+    private Calendar mFirstDayOfMonth;
+
+    /**
      * The start date of the range supported by this picker.
      */
-    private Calendar mMinDate = Calendar.getInstance();
+    private Calendar mMinDate;
 
     /**
      * The end date of the range supported by this picker.
      */
-    private Calendar mMaxDate = Calendar.getInstance();
+    private Calendar mMaxDate;
 
     /**
      * Date format for parsing dates.
@@ -304,6 +305,11 @@
     private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
 
     /**
+     * The current locale.
+     */
+    private Locale mCurrentLocale;
+
+    /**
      * The callback used to indicate the user changes the date.
      */
     public interface OnDateChangeListener {
@@ -330,6 +336,9 @@
     public CalendarView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, 0);
 
+        // initialization based on locale
+        setCurrentLocale(Locale.getDefault());
+
         TypedValue calendarViewStyle = new TypedValue();
         context.getTheme().resolveAttribute(R.attr.calendarViewStyle, calendarViewStyle, true);
         TypedArray attributesArray = context.obtainStyledAttributes(calendarViewStyle.resourceId,
@@ -413,6 +422,12 @@
         return mListView.isEnabled();
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        setCurrentLocale(newConfig.locale);
+    }
+
     /**
      * Gets the minimal date supported by this {@link CalendarView} in milliseconds
      * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
@@ -624,6 +639,41 @@
     }
 
     /**
+     * Sets the current locale.
+     *
+     * @param locale The current locale.
+     */
+    private void setCurrentLocale(Locale locale) {
+        if (locale.equals(mCurrentLocale)) {
+            return;
+        }
+
+        mCurrentLocale = locale;
+
+        mTempDate = getCalendarForLocale(mTempDate, locale);
+        mFirstDayOfMonth = getCalendarForLocale(mFirstDayOfMonth, locale);
+        mMinDate = getCalendarForLocale(mMinDate, locale);
+        mMaxDate = getCalendarForLocale(mMaxDate, locale);
+    }
+
+    /**
+     * Gets a calendar for locale bootstrapped with the value of a given calendar.
+     *
+     * @param oldCalendar The old calendar.
+     * @param locale The locale.
+     */
+    private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+        if (oldCalendar == null) {
+            return Calendar.getInstance(locale);
+        } else {
+            final long currentTimeMillis = oldCalendar.getTimeInMillis();
+            Calendar newCalendar = Calendar.getInstance(locale);
+            newCalendar.setTimeInMillis(currentTimeMillis);
+            return newCalendar;
+        }
+    }
+
+    /**
      * @return True if the <code>firstDate</code> is the same as the <code>
      * secondDate</code>.
      */
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 30fb927..4812283 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,10 +16,9 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.Widget;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -33,6 +32,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.NumberPicker.OnValueChangeListener;
 
+import com.android.internal.R;
+
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
@@ -89,23 +90,23 @@
 
     private final CalendarView mCalendarView;
 
+    private Locale mCurrentLocale;
+
     private OnDateChangedListener mOnDateChangedListener;
 
-    private Locale mMonthLocale;
-
-    private final Calendar mTempDate = Calendar.getInstance();
-
-    private final int mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
-
-    private final String[] mShortMonths = new String[mNumberOfMonths];
+    private String[] mShortMonths;
 
     private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
 
-    private final Calendar mMinDate = Calendar.getInstance();
+    private int mNumberOfMonths;
 
-    private final Calendar mMaxDate = Calendar.getInstance();
+    private Calendar mTempDate;
 
-    private final Calendar mCurrentDate = Calendar.getInstance();
+    private Calendar mMinDate;
+
+    private Calendar mMaxDate;
+
+    private Calendar mCurrentDate;
 
     private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
 
@@ -137,6 +138,9 @@
     public DatePicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
+        // initialization based on locale
+        setCurrentLocale(Locale.getDefault());
+
         TypedArray attributesArray = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
                 defStyle, 0);
         boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
@@ -213,7 +217,7 @@
         mMonthSpinner = (NumberPicker) findViewById(R.id.month);
         mMonthSpinner.setMinValue(0);
         mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
-        mMonthSpinner.setDisplayedValues(getShortMonths());
+        mMonthSpinner.setDisplayedValues(mShortMonths);
         mMonthSpinner.setOnLongPressUpdateInterval(200);
         mMonthSpinner.setOnValueChangedListener(onChangeListener);
 
@@ -363,6 +367,12 @@
         event.getText().add(selectedDateUtterance);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        setCurrentLocale(newConfig.locale);
+    }
+
     /**
      * Gets whether the {@link CalendarView} is shown.
      *
@@ -411,6 +421,48 @@
     }
 
     /**
+     * Sets the current locale.
+     *
+     * @param locale The current locale.
+     */
+    private void setCurrentLocale(Locale locale) {
+        if (locale.equals(mCurrentLocale)) {
+            return;
+        }
+
+        mCurrentLocale = locale;
+
+        mTempDate = getCalendarForLocale(mTempDate, locale);
+        mMinDate = getCalendarForLocale(mMinDate, locale);
+        mMaxDate = getCalendarForLocale(mMaxDate, locale);
+        mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+        mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+        mShortMonths = new String[mNumberOfMonths];
+        for (int i = 0; i < mNumberOfMonths; i++) {
+            mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
+                    DateUtils.LENGTH_MEDIUM);
+        }
+    }
+
+    /**
+     * Gets a calendar for locale bootstrapped with the value of a given calendar.
+     *
+     * @param oldCalendar The old calendar.
+     * @param locale The locale.
+     */
+    private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+        if (oldCalendar == null) {
+            return Calendar.getInstance(locale);
+        } else {
+            final long currentTimeMillis = oldCalendar.getTimeInMillis();
+            Calendar newCalendar = Calendar.getInstance(locale);
+            newCalendar.setTimeInMillis(currentTimeMillis);
+            return newCalendar;
+        }
+    }
+
+    /**
      * Reorders the spinners according to the date format that is
      * explicitly set by the user and if no such is set fall back
      * to the current locale's default format.
@@ -507,23 +559,6 @@
         }
     }
 
-    /**
-     * @return The short month abbreviations.
-     */
-    private String[] getShortMonths() {
-        final Locale currentLocale = Locale.getDefault();
-        if (currentLocale.equals(mMonthLocale)) {
-            return mShortMonths;
-        } else {
-            for (int i = 0; i < mNumberOfMonths; i++) {
-                mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
-                        DateUtils.LENGTH_MEDIUM);
-            }
-            mMonthLocale = currentLocale;
-            return mShortMonths;
-        }
-    }
-
     private boolean isNewDate(int year, int month, int dayOfMonth) {
         return (mCurrentDate.get(Calendar.YEAR) != year
                 || mCurrentDate.get(Calendar.MONTH) != dayOfMonth
@@ -569,7 +604,7 @@
 
         // make sure the month names are a zero based array
         // with the months in the month spinner
-        String[] displayedValues = Arrays.copyOfRange(getShortMonths(),
+        String[] displayedValues = Arrays.copyOfRange(mShortMonths,
                 mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
         mMonthSpinner.setDisplayedValues(displayedValues);
 
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index d6e426f..f48261d 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -16,16 +16,17 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.util.TypedValue;
 import android.view.ActionProvider;
 import android.view.MenuItem;
+import android.view.SubMenu;
 import android.view.View;
 
-import com.android.internal.R;
-
 /**
  * This is a provider for a share action. It is responsible for creating views
  * that enable data sharing and also to perform a default action for showing
@@ -102,17 +103,14 @@
         return activityChooserView;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onPerformDefaultAction(View actionView) {
-        if (actionView instanceof ActivityChooserView) {
-            ActivityChooserView activityChooserView = (ActivityChooserView) actionView;
-            activityChooserView.showPopup();
-        } else {
-            throw new IllegalArgumentException("actionView not instance of ActivityChooserView");
-        }
+    public boolean hasSubMenu() {
+        return true;
+    }
+
+    @Override
+    public void onPrepareSubMenu(SubMenu subMenu) {
+        // TODO Implement me
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e350ec4..6b4e454 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,11 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.util.FastMath;
-import com.android.internal.widget.EditableInputConnection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.R;
 import android.content.ClipData;
 import android.content.ClipData.Item;
@@ -132,6 +127,11 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.util.FastMath;
+import com.android.internal.widget.EditableInputConnection;
+
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.text.BreakIterator;
@@ -260,9 +260,12 @@
 
     class Drawables {
         final Rect mCompoundRect = new Rect();
-        Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight;
-        int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight;
-        int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight;
+        Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
+                mDrawableStart, mDrawableEnd;
+        int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
+                mDrawableSizeStart, mDrawableSizeEnd;
+        int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
+                mDrawableHeightStart, mDrawableHeightEnd;
         int mDrawablePadding;
     }
     private Drawables mDrawables;
@@ -352,6 +355,8 @@
         INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
     }
 
+    private boolean bResolvedDrawables = false;
+
     /*
      * Kick-start the font cache for the zygote process (to pay the cost of
      * initializing freetype for our default font only once).
@@ -494,7 +499,7 @@
         int buffertype = 0;
         boolean selectallonfocus = false;
         Drawable drawableLeft = null, drawableTop = null, drawableRight = null,
-            drawableBottom = null;
+            drawableBottom = null, drawableStart = null, drawableEnd = null;
         int drawablePadding = 0;
         int ellipsize = -1;
         boolean singleLine = false;
@@ -571,6 +576,14 @@
                 drawableBottom = a.getDrawable(attr);
                 break;
 
+            case com.android.internal.R.styleable.TextView_drawableStart:
+                drawableStart = a.getDrawable(attr);
+                break;
+
+            case com.android.internal.R.styleable.TextView_drawableEnd:
+                drawableEnd = a.getDrawable(attr);
+                break;
+
             case com.android.internal.R.styleable.TextView_drawablePadding:
                 drawablePadding = a.getDimensionPixelSize(attr, drawablePadding);
                 break;
@@ -980,6 +993,7 @@
 
         setCompoundDrawablesWithIntrinsicBounds(
             drawableLeft, drawableTop, drawableRight, drawableBottom);
+        setRelativeDrawablesIfNeeded(drawableStart, drawableEnd);
         setCompoundDrawablePadding(drawablePadding);
 
         // Same as setSingleLine(), but make sure the transformation method and the maximum number
@@ -1105,6 +1119,42 @@
         setTypeface(tf, styleIndex);
     }
 
+    private void setRelativeDrawablesIfNeeded(Drawable start, Drawable end) {
+        boolean hasRelativeDrawables = (start != null) || (end != null);
+        if (hasRelativeDrawables) {
+            Drawables dr = mDrawables;
+            if (dr == null) {
+                mDrawables = dr = new Drawables();
+            }
+            final Rect compoundRect = dr.mCompoundRect;
+            int[] state = getDrawableState();
+            if (start != null) {
+                start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight());
+                start.setState(state);
+                start.copyBounds(compoundRect);
+                start.setCallback(this);
+
+                dr.mDrawableStart = start;
+                dr.mDrawableSizeStart = compoundRect.width();
+                dr.mDrawableHeightStart = compoundRect.height();
+            } else {
+                dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+            }
+            if (end != null) {
+                end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight());
+                end.setState(state);
+                end.copyBounds(compoundRect);
+                end.setCallback(this);
+
+                dr.mDrawableEnd = end;
+                dr.mDrawableSizeEnd = compoundRect.width();
+                dr.mDrawableHeightEnd = compoundRect.height();
+            } else {
+                dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+            }
+        }
+    }
+
     @Override
     public void setEnabled(boolean enabled) {
         if (enabled == isEnabled()) {
@@ -1119,6 +1169,7 @@
             }
         }
         super.setEnabled(enabled);
+        prepareCursorControllers();
     }
 
     /**
@@ -1410,6 +1461,40 @@
     }
 
     /**
+     * Returns the start padding of the view, plus space for the start
+     * Drawable if any.
+     *
+     * @hide
+     */
+    public int getCompoundPaddingStart() {
+        resolveDrawables();
+        switch(getResolvedLayoutDirection()) {
+            default:
+            case LAYOUT_DIRECTION_LTR:
+                return getCompoundPaddingLeft();
+            case LAYOUT_DIRECTION_RTL:
+                return getCompoundPaddingRight();
+        }
+    }
+
+    /**
+     * Returns the end padding of the view, plus space for the end
+     * Drawable if any.
+     *
+     * @hide
+     */
+    public int getCompoundPaddingEnd() {
+        resolveDrawables();
+        switch(getResolvedLayoutDirection()) {
+            default:
+            case LAYOUT_DIRECTION_LTR:
+                return getCompoundPaddingRight();
+            case LAYOUT_DIRECTION_RTL:
+                return getCompoundPaddingLeft();
+        }
+    }
+
+    /**
      * Returns the extended top padding of the view, including both the
      * top Drawable if any and any extra space to keep more than maxLines
      * of text from showing.  It is only valid to call this after measuring.
@@ -1492,6 +1577,26 @@
     }
 
     /**
+     * Returns the total start padding of the view, including the start
+     * Drawable if any.
+     *
+     * @hide
+     */
+    public int getTotalPaddingStart() {
+        return getCompoundPaddingStart();
+    }
+
+    /**
+     * Returns the total end padding of the view, including the end
+     * Drawable if any.
+     *
+     * @hide
+     */
+    public int getTotalPaddingEnd() {
+        return getCompoundPaddingEnd();
+    }
+
+    /**
      * Returns the total top padding of the view, including the top
      * Drawable if any, the extra space to keep more than maxLines
      * from showing, and the vertical offset for gravity, if any.
@@ -1678,6 +1783,185 @@
     }
 
     /**
+     * Sets the Drawables (if any) to appear to the start of, above,
+     * to the end of, and below the text.  Use null if you do not
+     * want a Drawable there.  The Drawables must already have had
+     * {@link Drawable#setBounds} called.
+     *
+     * @attr ref android.R.styleable#TextView_drawableStart
+     * @attr ref android.R.styleable#TextView_drawableTop
+     * @attr ref android.R.styleable#TextView_drawableEnd
+     * @attr ref android.R.styleable#TextView_drawableBottom
+     *
+     * @hide
+     */
+    public void setCompoundDrawablesRelative(Drawable start, Drawable top,
+                                     Drawable end, Drawable bottom) {
+        Drawables dr = mDrawables;
+
+        final boolean drawables = start != null || top != null
+                || end != null || bottom != null;
+
+        if (!drawables) {
+            // Clearing drawables...  can we free the data structure?
+            if (dr != null) {
+                if (dr.mDrawablePadding == 0) {
+                    mDrawables = null;
+                } else {
+                    // We need to retain the last set padding, so just clear
+                    // out all of the fields in the existing structure.
+                    if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null);
+                    dr.mDrawableStart = null;
+                    if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null);
+                    dr.mDrawableTop = null;
+                    if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null);
+                    dr.mDrawableEnd = null;
+                    if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null);
+                    dr.mDrawableBottom = null;
+                    dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+                    dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+                    dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
+                    dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
+                }
+            }
+        } else {
+            if (dr == null) {
+                mDrawables = dr = new Drawables();
+            }
+
+            if (dr.mDrawableStart != start && dr.mDrawableStart != null) {
+                dr.mDrawableStart.setCallback(null);
+            }
+            dr.mDrawableStart = start;
+
+            if (dr.mDrawableTop != top && dr.mDrawableTop != null) {
+                dr.mDrawableTop.setCallback(null);
+            }
+            dr.mDrawableTop = top;
+
+            if (dr.mDrawableEnd != end && dr.mDrawableEnd != null) {
+                dr.mDrawableEnd.setCallback(null);
+            }
+            dr.mDrawableEnd = end;
+
+            if (dr.mDrawableBottom != bottom && dr.mDrawableBottom != null) {
+                dr.mDrawableBottom.setCallback(null);
+            }
+            dr.mDrawableBottom = bottom;
+
+            final Rect compoundRect = dr.mCompoundRect;
+            int[] state;
+
+            state = getDrawableState();
+
+            if (start != null) {
+                start.setState(state);
+                start.copyBounds(compoundRect);
+                start.setCallback(this);
+                dr.mDrawableSizeStart = compoundRect.width();
+                dr.mDrawableHeightStart = compoundRect.height();
+            } else {
+                dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+            }
+
+            if (end != null) {
+                end.setState(state);
+                end.copyBounds(compoundRect);
+                end.setCallback(this);
+                dr.mDrawableSizeEnd = compoundRect.width();
+                dr.mDrawableHeightEnd = compoundRect.height();
+            } else {
+                dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+            }
+
+            if (top != null) {
+                top.setState(state);
+                top.copyBounds(compoundRect);
+                top.setCallback(this);
+                dr.mDrawableSizeTop = compoundRect.height();
+                dr.mDrawableWidthTop = compoundRect.width();
+            } else {
+                dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
+            }
+
+            if (bottom != null) {
+                bottom.setState(state);
+                bottom.copyBounds(compoundRect);
+                bottom.setCallback(this);
+                dr.mDrawableSizeBottom = compoundRect.height();
+                dr.mDrawableWidthBottom = compoundRect.width();
+            } else {
+                dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
+            }
+        }
+
+        resolveDrawables();
+        invalidate();
+        requestLayout();
+    }
+
+    /**
+     * Sets the Drawables (if any) to appear to the start of, above,
+     * to the end of, and below the text.  Use 0 if you do not
+     * want a Drawable there. The Drawables' bounds will be set to
+     * their intrinsic bounds.
+     *
+     * @param start Resource identifier of the start Drawable.
+     * @param top Resource identifier of the top Drawable.
+     * @param end Resource identifier of the end Drawable.
+     * @param bottom Resource identifier of the bottom Drawable.
+     *
+     * @attr ref android.R.styleable#TextView_drawableStart
+     * @attr ref android.R.styleable#TextView_drawableTop
+     * @attr ref android.R.styleable#TextView_drawableEnd
+     * @attr ref android.R.styleable#TextView_drawableBottom
+     *
+     * @hide
+     */
+    public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
+            int bottom) {
+        resetResolvedDrawables();
+        final Resources resources = getContext().getResources();
+        setCompoundDrawablesRelativeWithIntrinsicBounds(
+                start != 0 ? resources.getDrawable(start) : null,
+                top != 0 ? resources.getDrawable(top) : null,
+                end != 0 ? resources.getDrawable(end) : null,
+                bottom != 0 ? resources.getDrawable(bottom) : null);
+    }
+
+    /**
+     * Sets the Drawables (if any) to appear to the start of, above,
+     * to the end of, and below the text.  Use null if you do not
+     * want a Drawable there. The Drawables' bounds will be set to
+     * their intrinsic bounds.
+     *
+     * @attr ref android.R.styleable#TextView_drawableStart
+     * @attr ref android.R.styleable#TextView_drawableTop
+     * @attr ref android.R.styleable#TextView_drawableEnd
+     * @attr ref android.R.styleable#TextView_drawableBottom
+     *
+     * @hide
+     */
+    public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
+            Drawable end, Drawable bottom) {
+
+        resetResolvedDrawables();
+        if (start != null) {
+            start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight());
+        }
+        if (end != null) {
+            end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight());
+        }
+        if (top != null) {
+            top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
+        }
+        if (bottom != null) {
+            bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
+        }
+        setCompoundDrawablesRelative(start, top, end, bottom);
+    }
+
+    /**
      * Returns drawables for the left, top, right, and bottom borders.
      */
     public Drawable[] getCompoundDrawables() {
@@ -1692,6 +1976,22 @@
     }
 
     /**
+     * Returns drawables for the start, top, end, and bottom borders.
+     *
+     * @hide
+     */
+    public Drawable[] getCompoundDrawablesRelative() {
+        final Drawables dr = mDrawables;
+        if (dr != null) {
+            return new Drawable[] {
+                dr.mDrawableStart, dr.mDrawableTop, dr.mDrawableEnd, dr.mDrawableBottom
+            };
+        } else {
+            return new Drawable[] { null, null, null, null };
+        }
+    }
+
+    /**
      * Sets the size of the padding between the compound drawables and
      * the text.
      *
@@ -2494,6 +2794,12 @@
             if (dr.mDrawableRight != null && dr.mDrawableRight.isStateful()) {
                 dr.mDrawableRight.setState(state);
             }
+            if (dr.mDrawableStart != null && dr.mDrawableStart.isStateful()) {
+                dr.mDrawableStart.setState(state);
+            }
+            if (dr.mDrawableEnd != null && dr.mDrawableEnd.isStateful()) {
+                dr.mDrawableEnd.setState(state);
+            }
         }
     }
 
@@ -2841,8 +3147,7 @@
 
                 // Do not change the movement method for text that support text selection as it
                 // would prevent an arbitrary cursor displacement.
-                final boolean hasTextSelection = this instanceof EditText || mTextIsSelectable;
-                if (mLinksClickable && !hasTextSelection) {
+                if (mLinksClickable && !textCanBeSelected()) {
                     setMovementMethod(LinkMovementMethod.getInstance());
                 }
             }
@@ -3546,7 +3851,17 @@
         mErrorWasChanged = true;
         final Drawables dr = mDrawables;
         if (dr != null) {
-            setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom);
+            switch (getResolvedLayoutDirection()) {
+                default:
+                case LAYOUT_DIRECTION_LTR:
+                    setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
+                            dr.mDrawableBottom);
+                    break;
+                case LAYOUT_DIRECTION_RTL:
+                    setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight,
+                            dr.mDrawableBottom);
+                    break;
+            }
         } else {
             setCompoundDrawables(null, null, icon, null);
         }
@@ -4048,6 +4363,9 @@
         if (mSelectionModifierCursorController != null) {
             observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
         }
+
+        // Resolve drawables as the layout direction has been resolved
+        resolveDrawables();
     }
 
     @Override
@@ -4077,6 +4395,8 @@
         }
 
         hideControllers();
+
+        resetResolvedDrawables();
     }
 
     @Override
@@ -4111,7 +4431,8 @@
         final boolean verified = super.verifyDrawable(who);
         if (!verified && mDrawables != null) {
             return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop ||
-                    who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom;
+                    who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom ||
+                    who == mDrawables.mDrawableStart || who == mDrawables.mDrawableEnd;
         }
         return verified;
     }
@@ -4132,6 +4453,12 @@
             if (mDrawables.mDrawableBottom != null) {
                 mDrawables.mDrawableBottom.jumpToCurrentState();
             }
+            if (mDrawables.mDrawableStart != null) {
+                mDrawables.mDrawableStart.jumpToCurrentState();
+            }
+            if (mDrawables.mDrawableEnd != null) {
+                mDrawables.mDrawableEnd.jumpToCurrentState();
+            }
         }
     }
 
@@ -4192,7 +4519,8 @@
         if (mDrawables != null) {
             final Drawables drawables = mDrawables;
             if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
-                who == drawables.mDrawableTop || who == drawables.mDrawableBottom) {
+                who == drawables.mDrawableTop || who == drawables.mDrawableBottom ||
+                who == drawables.mDrawableStart || who == drawables.mDrawableEnd) {
                 return getResolvedLayoutDirection();
             }
         }
@@ -4211,6 +4539,8 @@
                 if (dr.mDrawableTop != null) dr.mDrawableTop.mutate().setAlpha(alpha);
                 if (dr.mDrawableRight != null) dr.mDrawableRight.mutate().setAlpha(alpha);
                 if (dr.mDrawableBottom != null) dr.mDrawableBottom.mutate().setAlpha(alpha);
+                if (dr.mDrawableStart != null) dr.mDrawableStart.mutate().setAlpha(alpha);
+                if (dr.mDrawableEnd != null) dr.mDrawableEnd.mutate().setAlpha(alpha);
             }
             return true;
         }
@@ -4228,7 +4558,9 @@
      * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
      * selectable (text is not selectable by default).
      *
-     * Note that the content of an EditText is always selectable.
+     * Note that this method simply returns the state of this flag. Although this flag has to be set
+     * in order to select text in non-editable TextView, the content of an {@link EditText} can
+     * always be selected, independently of the value of this flag.
      *
      * @return True if the text displayed in this TextView can be selected by the user.
      *
@@ -4465,12 +4797,12 @@
             selStart = getSelectionStart();
             selEnd = getSelectionEnd();
 
-            if ((isCursorVisible() || mTextIsSelectable) && selStart >= 0 && isEnabled()) {
+            if (selStart >= 0) {
                 if (mHighlightPath == null)
                     mHighlightPath = new Path();
 
                 if (selStart == selEnd) {
-                    if (!mTextIsSelectable &&
+                    if (isCursorVisible() &&
                             (SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
                         if (mHighlightPathBogus) {
                             mHighlightPath.reset();
@@ -4489,7 +4821,7 @@
                         highlight = mHighlightPath;
                         drawCursor = mCursorCount > 0;
                     }
-                } else {
+                } else if (textCanBeSelected()) {
                     if (mHighlightPathBogus) {
                         mHighlightPath.reset();
                         mLayout.getSelectionPath(selStart, selEnd, mHighlightPath);
@@ -6212,6 +6544,15 @@
 
         int scrollx, scrolly;
 
+        // Convert to left, center, or right alignment.
+        if (a == Layout.Alignment.ALIGN_NORMAL) {
+            a = dir == Layout.DIR_LEFT_TO_RIGHT ? Layout.Alignment.ALIGN_LEFT :
+                Layout.Alignment.ALIGN_RIGHT;
+        } else if (a == Layout.Alignment.ALIGN_OPPOSITE){
+            a = dir == Layout.DIR_LEFT_TO_RIGHT ? Layout.Alignment.ALIGN_RIGHT :
+                Layout.Alignment.ALIGN_LEFT;
+        }
+
         if (a == Layout.Alignment.ALIGN_CENTER) {
             /*
              * Keep centered if possible, or, if it is too wide to fit,
@@ -6230,28 +6571,11 @@
                     scrollx = left;
                 }
             }
-        } else if (a == Layout.Alignment.ALIGN_NORMAL) {
-            /*
-             * Keep leading edge in view.
-             */
-
-            if (dir < 0) {
-                int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
-                scrollx = right - hspace;
-            } else {
-                scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
-            }
-        } else /* a == Layout.Alignment.ALIGN_OPPOSITE */ {
-            /*
-             * Keep trailing edge in view.
-             */
-
-            if (dir < 0) {
-                scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
-            } else {
-                int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
-                scrollx = right - hspace;
-            }
+        } else if (a == Layout.Alignment.ALIGN_LEFT) {
+            scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
+        } else { // a == Layout.Alignment.ALIGN_RIGHT
+            int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
+            scrollx = right - hspace;
         }
 
         if (ht < vspace) {
@@ -6293,20 +6617,24 @@
         int grav;
 
         switch (mLayout.getParagraphAlignment(line)) {
-            case ALIGN_NORMAL:
+            case ALIGN_LEFT:
                 grav = 1;
                 break;
-
-            case ALIGN_OPPOSITE:
+            case ALIGN_RIGHT:
                 grav = -1;
                 break;
-
+            case ALIGN_NORMAL:
+                grav = mLayout.getParagraphDirection(line);
+                break;
+            case ALIGN_OPPOSITE:
+                grav = -mLayout.getParagraphDirection(line);
+                break;
+            case ALIGN_CENTER:
             default:
                 grav = 0;
+                break;
         }
 
-        grav *= mLayout.getParagraphDirection(line);
-
         int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
         int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom();
 
@@ -7454,9 +7782,6 @@
     public boolean onTouchEvent(MotionEvent event) {
         final int action = event.getActionMasked();
 
-        if (hasInsertionController()) {
-            getInsertionController().onTouchEvent(event);
-        }
         if (hasSelectionController()) {
             getSelectionController().onTouchEvent(event);
         }
@@ -7884,7 +8209,8 @@
         // prepareCursorController() relies on this method.
         // If you change this condition, make sure prepareCursorController is called anywhere
         // the value of this condition might be changed.
-        return mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily();
+        if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
+        return isTextEditable() || (mTextIsSelectable && mText instanceof Spannable && isEnabled());
     }
 
     private boolean canCut() {
@@ -7972,6 +8298,10 @@
         final int minOffset = extractRangeStartFromLong(lastTouchOffsets);
         final int maxOffset = extractRangeEndFromLong(lastTouchOffsets);
 
+        // Safety check in case standard touch event handling has been bypassed
+        if (minOffset < 0 || minOffset >= mText.length()) return false;
+        if (maxOffset < 0 || maxOffset >= mText.length()) return false;
+
         int selectionStart, selectionEnd;
 
         // If a URLSpan (web address, email, phone...) is found at that position, select it.
@@ -9727,13 +10057,6 @@
         public void hide();
 
         /**
-         * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
-         * a chance to become active and/or visible.
-         * @param event The touch event
-         */
-        public boolean onTouchEvent(MotionEvent event);
-
-        /**
          * Called when the view is detached from window. Perform house keeping task, such as
          * stopping Runnable thread that would otherwise keep a reference on the context, thus
          * preventing the activity from being recycled.
@@ -9760,10 +10083,6 @@
             }
         }
 
-        public boolean onTouchEvent(MotionEvent ev) {
-            return false;
-        }
-
         public void onTouchModeChanged(boolean isInTouchMode) {
             if (!isInTouchMode) {
                 hide();
@@ -9822,52 +10141,49 @@
             if (mEndHandle != null) mEndHandle.hide();
         }
 
-        public boolean onTouchEvent(MotionEvent event) {
+        public void onTouchEvent(MotionEvent event) {
             // This is done even when the View does not have focus, so that long presses can start
             // selection and tap can move cursor from this tap position.
-            if (isTextEditable() || mTextIsSelectable) {
-                switch (event.getActionMasked()) {
-                    case MotionEvent.ACTION_DOWN:
-                        final float x = event.getX();
-                        final float y = event.getY();
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_DOWN:
+                    final float x = event.getX();
+                    final float y = event.getY();
 
-                        // Remember finger down position, to be able to start selection from there
-                        mMinTouchOffset = mMaxTouchOffset = getOffsetForPosition(x, y);
+                    // Remember finger down position, to be able to start selection from there
+                    mMinTouchOffset = mMaxTouchOffset = getOffsetForPosition(x, y);
 
-                        // Double tap detection
-                        long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
-                        if (duration <= ViewConfiguration.getDoubleTapTimeout() &&
-                                isPositionOnText(x, y)) {
-                            final float deltaX = x - mPreviousTapPositionX;
-                            final float deltaY = y - mPreviousTapPositionY;
-                            final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
-                            if (distanceSquared < mSquaredTouchSlopDistance) {
-                                showSuggestions();
-                                mDiscardNextActionUp = true;
-                            }
+                    // Double tap detection
+                    long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
+                    if (duration <= ViewConfiguration.getDoubleTapTimeout() &&
+                            isPositionOnText(x, y)) {
+                        final float deltaX = x - mPreviousTapPositionX;
+                        final float deltaY = y - mPreviousTapPositionY;
+                        final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
+                        if (distanceSquared < mSquaredTouchSlopDistance) {
+                            showSuggestions();
+                            mDiscardNextActionUp = true;
                         }
+                    }
 
-                        mPreviousTapPositionX = x;
-                        mPreviousTapPositionY = y;
+                    mPreviousTapPositionX = x;
+                    mPreviousTapPositionY = y;
 
-                        break;
+                    break;
 
-                    case MotionEvent.ACTION_POINTER_DOWN:
-                    case MotionEvent.ACTION_POINTER_UP:
-                        // Handle multi-point gestures. Keep min and max offset positions.
-                        // Only activated for devices that correctly handle multi-touch.
-                        if (mContext.getPackageManager().hasSystemFeature(
-                                PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
-                            updateMinAndMaxOffsets(event);
-                        }
-                        break;
+                case MotionEvent.ACTION_POINTER_DOWN:
+                case MotionEvent.ACTION_POINTER_UP:
+                    // Handle multi-point gestures. Keep min and max offset positions.
+                    // Only activated for devices that correctly handle multi-touch.
+                    if (mContext.getPackageManager().hasSystemFeature(
+                            PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
+                        updateMinAndMaxOffsets(event);
+                    }
+                    break;
 
-                    case MotionEvent.ACTION_UP:
-                        mPreviousTapUpTime = SystemClock.uptimeMillis();
-                        break;
-                }
+                case MotionEvent.ACTION_UP:
+                    mPreviousTapUpTime = SystemClock.uptimeMillis();
+                    break;
             }
-            return false;
         }
 
         /**
@@ -10289,6 +10605,68 @@
         return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT);
     }
 
+    /**
+     * Subclasses will need to override this method to implement their own way of resolving
+     * drawables depending on the layout direction.
+     *
+     * A call to the super method will be required from the subclasses implementation.
+     *
+     */
+    protected void resolveDrawables() {
+        // No need to resolve twice
+        if (bResolvedDrawables) {
+            return;
+        }
+        // No drawable to resolve
+        if (mDrawables == null) {
+            return;
+        }
+        // No relative drawable to resolve
+        if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
+            bResolvedDrawables = true;
+            return;
+        }
+
+        Drawables dr = mDrawables;
+        switch(getResolvedLayoutDirection()) {
+            case LAYOUT_DIRECTION_RTL:
+                if (dr.mDrawableStart != null) {
+                    dr.mDrawableRight = dr.mDrawableStart;
+
+                    dr.mDrawableSizeRight = dr.mDrawableSizeStart;
+                    dr.mDrawableHeightRight = dr.mDrawableHeightStart;
+                }
+                if (dr.mDrawableEnd != null) {
+                    dr.mDrawableLeft = dr.mDrawableEnd;
+
+                    dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
+                    dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
+                }
+                break;
+
+            case LAYOUT_DIRECTION_LTR:
+            default:
+                if (dr.mDrawableStart != null) {
+                    dr.mDrawableLeft = dr.mDrawableStart;
+
+                    dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
+                    dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
+                }
+                if (dr.mDrawableEnd != null) {
+                    dr.mDrawableRight = dr.mDrawableEnd;
+
+                    dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
+                    dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
+                }
+                break;
+        }
+        bResolvedDrawables = true;
+    }
+
+    protected void resetResolvedDrawables() {
+        bResolvedDrawables = false;
+    }
+
     @ViewDebug.ExportedProperty(category = "text")
     private CharSequence            mText;
     private CharSequence            mTransformed;
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 423e735c..0547438 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -20,6 +20,7 @@
 
 import android.annotation.Widget;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,6 +33,7 @@
 
 import java.text.DateFormatSymbols;
 import java.util.Calendar;
+import java.util.Locale;
 
 /**
  * A view for selecting the time of day, in either 24 hour or AM/PM mode. The
@@ -92,6 +94,8 @@
 
     private Calendar mTempCalendar;
 
+    private Locale mCurrentLocale;
+
     /**
      * The callback interface used to indicate the time has been adjusted.
      */
@@ -116,6 +120,9 @@
     public TimePicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
+        // initialization based on locale
+        setCurrentLocale(Locale.getDefault());
+
         // process style attributes
         TypedArray attributesArray = context.obtainStyledAttributes(
                 attrs, R.styleable.TimePicker, defStyle, 0);
@@ -211,8 +218,6 @@
         updateHourControl();
         updateAmPmControl();
 
-        // initialize to current time
-        mTempCalendar = Calendar.getInstance();
         setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
 
         // set to current time
@@ -248,6 +253,25 @@
         return mIsEnabled;
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        setCurrentLocale(newConfig.locale);
+    }
+
+    /**
+     * Sets the current locale.
+     *
+     * @param locale The current locale.
+     */
+    private void setCurrentLocale(Locale locale) {
+        if (locale.equals(mCurrentLocale)) {
+            return;
+        }
+        mCurrentLocale = locale;
+        mTempCalendar = Calendar.getInstance(locale);
+    }
+
     /**
      * Used to save / restore state of time picker
      */
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
index 1ac191b..8c2c405 100755
--- a/core/java/com/android/internal/os/PkgUsageStats.java
+++ b/core/java/com/android/internal/os/PkgUsageStats.java
@@ -19,6 +19,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * implementation of PkgUsageStats associated with an
  * application package.
@@ -28,6 +31,7 @@
     public String packageName;
     public int launchCount;
     public long usageTime;
+    public Map<String, Long> componentResumeTimes;
     
     public static final Parcelable.Creator<PkgUsageStats> CREATOR
     = new Parcelable.Creator<PkgUsageStats>() {
@@ -46,31 +50,45 @@
         + " " + packageName + "}";
     }
     
-    public PkgUsageStats(String pkgName, int count, long time) {
+    public PkgUsageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
         packageName = pkgName;
         launchCount = count;
         usageTime = time;
+        componentResumeTimes = new HashMap<String, Long>(lastResumeTimes);
     }
     
     public PkgUsageStats(Parcel source) {
         packageName = source.readString();
         launchCount = source.readInt();
         usageTime = source.readLong();
+        final int N = source.readInt();
+        componentResumeTimes = new HashMap<String, Long>(N);
+        for (int i = 0; i < N; i++) {
+            String component = source.readString();
+            long lastResumeTime = source.readLong();
+            componentResumeTimes.put(component, lastResumeTime);
+        }
     }
     
     public PkgUsageStats(PkgUsageStats pStats) {
         packageName = pStats.packageName;
         launchCount = pStats.launchCount;
         usageTime = pStats.usageTime;
+        componentResumeTimes = new HashMap<String, Long>(pStats.componentResumeTimes);
     }
 
     public int describeContents() {
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int parcelableFlags){
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeString(packageName);
         dest.writeInt(launchCount);
         dest.writeLong(usageTime);
+        dest.writeInt(componentResumeTimes.size());
+        for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
+            dest.writeString(ent.getKey());
+            dest.writeLong(ent.getValue());
+        }
     }
 }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index a3b7795..9af7e96 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -900,6 +900,7 @@
             }
         }
 
+        boolean usingWrapper = false;
         if (pipeFd != null && pid > 0) {
             DataInputStream is = new DataInputStream(new FileInputStream(pipeFd));
             int innerPid = -1;
@@ -924,6 +925,7 @@
                 if (parentPid > 0) {
                     Log.i(TAG, "Wrapped process has pid " + innerPid);
                     pid = innerPid;
+                    usingWrapper = true;
                 } else {
                     Log.w(TAG, "Wrapped process reported a pid that is not a child of "
                             + "the process that we forked: childPid=" + pid
@@ -934,6 +936,7 @@
 
         try {
             mSocketOutStream.writeInt(pid);
+            mSocketOutStream.writeBoolean(usingWrapper);
         } catch (IOException ex) {
             Log.e(TAG, "Error reading from command socket", ex);
             return true;
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index b86eb13..9c06d69 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -20,7 +20,8 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.util.Log;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.util.SparseBooleanArray;
 import android.view.MenuItem;
 import android.view.SoundEffectConstants;
@@ -60,6 +61,9 @@
 
     private OpenOverflowRunnable mPostedOpenRunnable;
 
+    final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
+    int mOpenSubMenuId;
+
     public ActionMenuPresenter() {
         super(com.android.internal.R.layout.action_menu_layout,
                 com.android.internal.R.layout.action_menu_item_layout);
@@ -196,8 +200,12 @@
             topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu();
         }
         View anchor = findViewForItem(topSubMenu.getItem());
-        if (anchor == null) return false;
+        if (anchor == null) {
+            if (mOverflowButton == null) return false;
+            anchor = mOverflowButton;
+        }
 
+        mOpenSubMenuId = subMenu.getItem().getItemId();
         mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu);
         mActionButtonPopup.setAnchorView(anchor);
         mActionButtonPopup.show();
@@ -426,6 +434,57 @@
         super.onCloseMenu(menu, allMenusAreClosing);
     }
 
+    @Override
+    public Parcelable onSaveInstanceState() {
+        SavedState state = new SavedState();
+        state.openSubMenuId = mOpenSubMenuId;
+        return state;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        SavedState saved = (SavedState) state;
+        if (saved.openSubMenuId > 0) {
+            MenuItem item = mMenu.findItem(saved.openSubMenuId);
+            if (item != null) {
+                SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+                onSubMenuSelected(subMenu);
+            }
+        }
+    }
+
+    private static class SavedState implements Parcelable {
+        public int openSubMenuId;
+
+        SavedState() {
+        }
+
+        SavedState(Parcel in) {
+            openSubMenuId = in.readInt();
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(openSubMenuId);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR
+                = new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
     private class OverflowMenuButton extends ImageButton implements ActionMenuChildView {
         public OverflowMenuButton(Context context) {
             super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
@@ -460,6 +519,7 @@
         public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
                 boolean overflowOnly) {
             super(context, menu, anchorView, overflowOnly);
+            setCallback(mPopupPresenterCallback);
         }
 
         @Override
@@ -482,6 +542,8 @@
                 // Give a reasonable anchor to nested submenus.
                 setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
             }
+
+            setCallback(mPopupPresenterCallback);
         }
 
         @Override
@@ -489,6 +551,20 @@
             super.onDismiss();
             mSubMenu.close();
             mActionButtonPopup = null;
+            mOpenSubMenuId = 0;
+        }
+    }
+
+    private class PopupPresenterCallback implements MenuPresenter.Callback {
+
+        @Override
+        public boolean onOpenSubMenu(MenuBuilder subMenu) {
+            mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
+            return false;
+        }
+
+        @Override
+        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index ddbb08c..ed9d34a 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -39,6 +39,8 @@
 
     protected MenuView mMenuView;
 
+    private int mId;
+
     /**
      * Construct a new BaseMenuPresenter.
      *
@@ -200,4 +202,12 @@
     public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
         return false;
     }
+
+    public int getId() {
+        return mId;
+    }
+
+    public void setId(int id) {
+        mId = id;
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
index f717904..56128d4 100644
--- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
@@ -23,6 +23,7 @@
 import android.util.SparseArray;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -35,7 +36,12 @@
     private IconMenuItemView mMoreView;
     private int mMaxItems = -1;
 
+    int mOpenSubMenuId;
+    SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback();
+    MenuDialogHelper mOpenSubMenu;
+
     private static final String VIEWS_TAG = "android:menu:icon";
+    private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu";
 
     public IconMenuPresenter() {
         super(com.android.internal.R.layout.icon_menu_layout,
@@ -86,7 +92,11 @@
         if (!subMenu.hasVisibleItems()) return false;
 
         // The window manager will give us a token.
-        new MenuDialogHelper(subMenu).show(null);
+        MenuDialogHelper helper = new MenuDialogHelper(subMenu);
+        helper.setPresenterCallback(mSubMenuPresenterCallback);
+        helper.show(null);
+        mOpenSubMenu = helper;
+        mOpenSubMenuId = subMenu.getItem().getItemId();
         super.onSubMenuSelected(subMenu);
         return true;
     }
@@ -137,5 +147,47 @@
         if (viewStates != null) {
             ((View) mMenuView).restoreHierarchyState(viewStates);
         }
+        int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0);
+        if (subMenuId > 0 && mMenu != null) {
+            MenuItem item = mMenu.findItem(subMenuId);
+            if (item != null) {
+                onSubMenuSelected((SubMenuBuilder) item.getSubMenu());
+            }
+        }
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        if (mMenuView == null) {
+            return null;
+        }
+
+        Bundle state = new Bundle();
+        saveHierarchyState(state);
+        if (mOpenSubMenuId > 0) {
+            state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId);
+        }
+        return state;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        restoreHierarchyState((Bundle) state);
+    }
+
+    class SubMenuPresenterCallback implements MenuPresenter.Callback {
+        @Override
+        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+            mOpenSubMenuId = 0;
+            mOpenSubMenu.dismiss();
+            mOpenSubMenu = null;
+        }
+
+        @Override
+        public boolean onOpenSubMenu(MenuBuilder subMenu) {
+            mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
+            return false;
+        }
+
     }
 }
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 27e4191..146c7ac 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -47,6 +47,8 @@
     private Callback mCallback;
     private MenuAdapter mAdapter;
 
+    private int mId;
+
     public static final String VIEWS_TAG = "android:menu:list";
 
     /**
@@ -182,6 +184,31 @@
         }
     }
 
+    public void setId(int id) {
+        mId = id;
+    }
+
+    @Override
+    public int getId() {
+        return mId;
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        if (mMenuView == null) {
+            return null;
+        }
+
+        Bundle state = new Bundle();
+        saveHierarchyState(state);
+        return state;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        restoreHierarchyState((Bundle) state);
+    }
+
     private class MenuAdapter extends BaseAdapter {
         public int getCount() {
             ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index fdfa954..b0b49213 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -25,9 +25,10 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.os.Parcelable;
-import android.util.Log;
 import android.util.SparseArray;
+import android.view.ActionProvider;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -38,7 +39,6 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -49,6 +49,8 @@
 public class MenuBuilder implements Menu {
     private static final String LOGTAG = "MenuBuilder";
 
+    private static final String PRESENTER_KEY = "android:menu:presenters";
+
     private static final int[]  sCategoryToOrder = new int[] {
         1, /* No category */
         4, /* CONTAINER */
@@ -254,6 +256,58 @@
         return result;
     }
 
+    private void dispatchSaveInstanceState(Bundle outState) {
+        if (mPresenters.isEmpty()) return;
+
+        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
+
+        for (WeakReference<MenuPresenter> ref : mPresenters) {
+            final MenuPresenter presenter = ref.get();
+            if (presenter == null) {
+                mPresenters.remove(ref);
+            } else {
+                final int id = presenter.getId();
+                if (id > 0) {
+                    final Parcelable state = presenter.onSaveInstanceState();
+                    if (state != null) {
+                        presenterStates.put(id, state);
+                    }
+                }
+            }
+        }
+
+        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
+    }
+
+    private void dispatchRestoreInstanceState(Bundle state) {
+        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
+
+        if (presenterStates == null || mPresenters.isEmpty()) return;
+
+        for (WeakReference<MenuPresenter> ref : mPresenters) {
+            final MenuPresenter presenter = ref.get();
+            if (presenter == null) {
+                mPresenters.remove(ref);
+            } else {
+                final int id = presenter.getId();
+                if (id > 0) {
+                    Parcelable parcel = presenterStates.get(id);
+                    if (parcel != null) {
+                        presenter.onRestoreInstanceState(parcel);
+                    }
+                }
+            }
+        }
+    }
+
+    public void savePresenterStates(Bundle outState) {
+        dispatchSaveInstanceState(outState);
+    }
+
+    public void restorePresenterStates(Bundle state) {
+        dispatchRestoreInstanceState(state);
+    }
+
     public void setCallback(Callback cb) {
         mCallback = cb;
     }
@@ -754,7 +808,12 @@
         } else if (item.hasSubMenu()) {
             close(false);
 
-            invoked |= dispatchSubMenuSelected((SubMenuBuilder) item.getSubMenu());
+            final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+            final ActionProvider provider = item.getActionProvider();
+            if (provider != null && provider.hasSubMenu()) {
+                provider.onPrepareSubMenu(subMenu);
+            }
+            invoked |= dispatchSubMenuSelected(subMenu);
             if (!invoked) close(true);
         } else {
             if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 20b7d80..0a7313c 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -164,10 +164,7 @@
             }
         }
 
-        if (mActionProvider != null) {
-            // The action view is created by the provider in this case.
-            View actionView = getActionView();
-            mActionProvider.onPerformDefaultAction(actionView);
+        if (mActionProvider != null && mActionProvider.onPerformDefaultAction()) {
             return true;
         }
 
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index cffbb4e..4ecc828 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.Parcelable;
 import android.util.DisplayMetrics;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -296,4 +297,18 @@
             return convertView;
         }
     }
+
+    @Override
+    public int getId() {
+        return 0;
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        return null;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java
index bd66448..d913a39 100644
--- a/core/java/com/android/internal/view/menu/MenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/MenuPresenter.java
@@ -17,6 +17,7 @@
 package com.android.internal.view.menu;
 
 import android.content.Context;
+import android.os.Parcelable;
 import android.view.Menu;
 import android.view.ViewGroup;
 
@@ -125,4 +126,24 @@
      * @return true if this presenter collapsed the action view, false otherwise.
      */
     public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item);
+
+    /**
+     * Returns an ID for determining how to save/restore instance state.
+     * @return a valid ID value.
+     */
+    public int getId();
+
+    /**
+     * Returns a Parcelable describing the current state of the presenter.
+     * It will be passed to the {@link #onRestoreInstanceState(Parcelable)}
+     * method of the presenter sharing the same ID later.
+     * @return The saved instance state
+     */
+    public Parcelable onSaveInstanceState();
+
+    /**
+     * Supplies the previously saved instance state to be restored.
+     * @param state The previously saved instance state
+     */
+    public void onRestoreInstanceState(Parcelable state);
 }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 09bc1fc..595753a 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -337,6 +337,7 @@
         if (mActionMenuPresenter == null) {
             mActionMenuPresenter = new ActionMenuPresenter();
             mActionMenuPresenter.setCallback(cb);
+            mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter);
             mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
         }
 
@@ -1301,5 +1302,19 @@
             item.setActionViewExpanded(false);
             return true;
         }
+
+        @Override
+        public int getId() {
+            return 0;
+        }
+
+        @Override
+        public Parcelable onSaveInstanceState() {
+            return null;
+        }
+
+        @Override
+        public void onRestoreInstanceState(Parcelable state) {
+        }
     }
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 63fa504..58e7c8d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -224,22 +224,14 @@
 LOCAL_SHARED_LIBRARIES += libbluedroid libdbus
 endif
 
-ifneq ($(TARGET_SIMULATOR),true)
 LOCAL_SHARED_LIBRARIES += \
 	libdl
-  # we need to access the private Bionic header
-  # <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
-  LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
-endif
+# we need to access the private Bionic header
+# <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
 
 LOCAL_LDLIBS += -lpthread -ldl
 
-ifeq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
-LOCAL_LDLIBS += -lrt
-endif
-endif
-
 ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
 	LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
 endif
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index 203b5ef..d54981e 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -67,10 +67,35 @@
 #endif
 }
 
-// Return the number from the first file which exists and contains data
-static jlong tryBoth(char const* a, char const* b) {
-    jlong num = readNumber(a);
-    return num >= 0 ? num : readNumber(b);
+static const char* mobile_iface_list[] = {
+    "rmnet0",
+    "rmnet1",
+    "rmnet2",
+    "rmnet3",
+    "ppp0",
+    0
+};
+
+static jlong getAll(const char** iface_list, const char* what) {
+
+    char filename[80];
+    int idx = 0;
+    bool supported = false;
+    jlong total = 0;
+    while (iface_list[idx] != 0) {
+
+        snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s",
+                 iface_list[idx], what);
+        jlong number = readNumber(filename);
+        if (number >= 0) {
+            supported = true;
+            total += number;
+        }
+        idx++;
+    }
+    if (supported) return total;
+
+    return -1;
 }
 
 // Returns the sum of numbers from the specified path under /sys/class/net/*,
@@ -108,27 +133,19 @@
 // each file every time (rather than caching which ones exist).
 
 static jlong getMobileTxPackets(JNIEnv* env, jobject clazz) {
-    return tryBoth(
-            "/sys/class/net/rmnet0/statistics/tx_packets",
-            "/sys/class/net/ppp0/statistics/tx_packets");
+    return getAll(mobile_iface_list, "tx_packets");
 }
 
 static jlong getMobileRxPackets(JNIEnv* env, jobject clazz) {
-    return tryBoth(
-            "/sys/class/net/rmnet0/statistics/rx_packets",
-            "/sys/class/net/ppp0/statistics/rx_packets");
+    return getAll(mobile_iface_list, "rx_packets");
 }
 
 static jlong getMobileTxBytes(JNIEnv* env, jobject clazz) {
-    return tryBoth(
-            "/sys/class/net/rmnet0/statistics/tx_bytes",
-            "/sys/class/net/ppp0/statistics/tx_bytes");
+    return getAll(mobile_iface_list, "tx_bytes");
 }
 
 static jlong getMobileRxBytes(JNIEnv* env, jobject clazz) {
-    return tryBoth(
-            "/sys/class/net/rmnet0/statistics/rx_bytes",
-            "/sys/class/net/ppp0/statistics/rx_bytes");
+    return getAll(mobile_iface_list, "rx_bytes");
 }
 
 static jlong getData(JNIEnv* env, const char* what, jstring javaInterface) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9c2133f..cfc5041 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3015,6 +3015,10 @@
         <attr name="drawableLeft" format="reference|color" />
         <!-- The drawable to be drawn to the right of the text. -->
         <attr name="drawableRight" format="reference|color" />
+        <!-- The drawable to be drawn to the start of the text. -->
+        <attr name="drawableStart" format="reference|color" />
+        <!-- The drawable to be drawn to the end of the text. -->
+        <attr name="drawableEnd" format="reference|color" />
         <!-- The padding between the drawables and the text. -->
         <attr name="drawablePadding" format="dimension" />
         <!-- Extra spacing between lines of text. -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index d05685c..547a192 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -74,4 +74,9 @@
   <item type="id" name="rowTypeId" />
   <item type="id" name="up" />
   <item type="id" name="action_menu_divider" />
+  <item type="id" name="icon_menu_presenter" />
+  <item type="id" name="list_menu_presenter" />
+  <item type="id" name="action_menu_presenter" />
+  <item type="id" name="overflow_menu_presenter" />
+  <item type="id" name="popup_submenu_presenter" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f7701f2..6dedc83 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1826,4 +1826,7 @@
   <public type="color" name="holo_purple" />
   <public type="color" name="holo_blue_bright" />
 
+  <public type="attr" name="drawableStart" />
+  <public type="attr" name="drawableEnd" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 97a8c0b..70c204e 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2038,13 +2038,13 @@
     <string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfono<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
-    <string name="autofill_area_code_re">area code</string>
+    <string name="autofill_area_code_re">area.*code|acode|area</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
-    <string name="autofill_phone_prefix_re">^-$|\\)$|prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
+    <string name="autofill_phone_prefix_re">prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
-    <string name="autofill_phone_suffix_re">^-$|suffix</string>
+    <string name="autofill_phone_suffix_re">suffix</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
     <string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string>
@@ -2077,17 +2077,49 @@
     <string name="autofill_country_code_re">country.*code|ccode|_cc</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
-    <string name="autofill_area_code_notext_re">^\($</string>
+    <string name="autofill_area_code_notext_re">^\\($</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
-    <string name="autofill_phone_prefix_separator_re">^-$|^\)$</string>
+    <string name="autofill_phone_prefix_separator_re">^-$|^\\)$</string>
 
     <!-- Do not translate. Regex used by AutoFill. -->
     <string name="autofill_phone_suffix_separator_re">^-$</string>
 
-    <!-- Do not translate. Regex used by AutoFill. -->
-    <!-- Ex: ************1234 -->
-    <string name="credit_card_number_preview_format">$1</string>
+    <!-- Label in a web form for "Province" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_province">Province</string>
+
+    <!-- Label in a web form for "Postal code" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_postal_code">Postal code</string>
+
+    <!-- Label in a web form for "State" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_state">State</string>
+
+    <!-- Label in a web form for "ZIP code" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_zip_code">ZIP code</string>
+
+    <!-- Label in a web form for "County" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_county">County</string>
+
+    <!-- Label in a web form for "Island" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_island">Island</string>
+
+    <!-- Label in a web form for "District" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_district">District</string>
+
+    <!-- Label in a web form for "Department" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_department">Department</string>
+
+    <!-- Label in a web form for "Prefecture" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_prefecture">Prefecture</string>
+
+    <!-- Label in a web form for "Parish" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_parish">Parish</string>
+
+    <!-- Label in a web form for "Area" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_area">Area</string>
+
+    <!-- Label in a web form for "Emirate" [CHAR-LIMIT=NONE]  -->
+    <string name="autofill_emirate">Emirate</string>
 
     <!-- Title of an application permission, listed so the user can choose whether
         they want to allow the application to do this. -->
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 00f47fa..b2ebb08 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -12,7 +12,7 @@
 	$(call all-java-files-under, EnabledTestApp/src)
 
 LOCAL_DX_FLAGS := --core-library
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib mockwebserver
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib mockwebserver guava
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksCoreTests
 
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 40fa552..146466f 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1242,6 +1242,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.animation.BasicAnimatorActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/core/tests/coretests/res/layout/animator_basic.xml b/core/tests/coretests/res/layout/animator_basic.xml
new file mode 100644
index 0000000..7b8ef11
--- /dev/null
+++ b/core/tests/coretests/res/layout/animator_basic.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/animatingButton"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
new file mode 100644
index 0000000..65f2b8e
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package android.animation;
+
+import android.widget.Button;
+import com.android.frameworks.coretests.R;
+
+/**
+ * Listener tests for AnimatorSet.
+ */
+public class AnimatorSetEventsTest extends EventsTest {
+
+    @Override
+    public void setUp() throws Exception {
+        final BasicAnimatorActivity activity = getActivity();
+        Button button = (Button) activity.findViewById(R.id.animatingButton);
+
+        ObjectAnimator xAnim = ObjectAnimator.ofFloat(button, "translationX", 0, 100);
+        ObjectAnimator yAnim = ObjectAnimator.ofFloat(button, "translationX", 0, 100);
+        mAnimator = new AnimatorSet();
+        ((AnimatorSet)mAnimator).playSequentially(xAnim, yAnim);
+
+        super.setUp();
+    }
+
+}
diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
new file mode 100644
index 0000000..93808d9
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import com.android.frameworks.coretests.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class BasicAnimatorActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.animator_basic);
+    }
+}
diff --git a/core/tests/coretests/src/android/animation/EventsTest.java b/core/tests/coretests/src/android/animation/EventsTest.java
new file mode 100644
index 0000000..f970ffc
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/EventsTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import android.os.Handler;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for the various lifecycle events of Animators. This abstract class is subclassed by
+ * concrete implementations that provide the actual Animator objects being tested. All of the
+ * testing mechanisms are in this class; the subclasses are only responsible for providing
+ * the mAnimator object.
+ *
+ * This test is more complicated than a typical synchronous test because much of the functionality
+ * must happen on the UI thread. Some tests do this by using the UiThreadTest annotation to
+ * automatically run the whole test on that thread. Other tests must run on the UI thread and also
+ * wait for some later event to occur before ending. These tests use a combination of an
+ * AbstractFuture mechanism and a delayed action to release that Future later.
+ */
+public abstract class EventsTest
+        extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
+
+    private static final int ANIM_DURATION = 400;
+    private static final int ANIM_DELAY = 100;
+    private static final int ANIM_MID_DURATION = ANIM_DURATION / 2;
+    private static final int ANIM_MID_DELAY = ANIM_DELAY / 2;
+
+    private boolean mRunning;  // tracks whether we've started the animator
+    private boolean mCanceled; // trackes whether we've canceled the animator
+    private Animator.AnimatorListener mFutureListener; // mechanism for delaying the end of the test
+    private FutureWaiter mFuture; // Mechanism for waiting for the UI test to complete
+    private Animator.AnimatorListener mListener; // Listener that handles/tests the events
+
+    protected Animator mAnimator; // The animator used in the tests. Must be set in subclass
+                                  // setup() method prior to calling the superclass setup()
+
+    /**
+     * Cancels the given animator. Used to delay cancelation until some later time (after the
+     * animator has started playing).
+     */
+    static class Canceler implements Runnable {
+        Animator mAnim;
+        public Canceler(Animator anim) {
+            mAnim = anim;
+        }
+        @Override
+        public void run() {
+            mAnim.cancel();
+        }
+    };
+
+    /**
+     * Releases the given Future object when the listener's end() event is called. Specifically,
+     * it releases it after some further delay, to give the test time to do other things right
+     * after an animation ends.
+     */
+    static class FutureReleaseListener extends AnimatorListenerAdapter {
+        FutureWaiter mFuture;
+
+        public FutureReleaseListener(FutureWaiter future) {
+            mFuture = future;
+        }
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            Handler handler = new Handler();
+            handler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mFuture.release();
+                }
+            }, ANIM_MID_DURATION);
+        }
+    };
+
+    public EventsTest() {
+        super(BasicAnimatorActivity.class);
+    }
+
+
+    /**
+     * Sets up the fields used by each test. Subclasses must override this method to create
+     * the protected mAnimator object used in all tests. Overrides must create that animator
+     * and then call super.setup(), where further properties are set on that animator.
+     * @throws Exception
+     */
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // mListener is the main testing mechanism of this file. The asserts of each test
+        // are embedded in the listener callbacks that it implements.
+        mListener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                // This should only be called on an animation that has been started and not
+                // yet canceled or ended
+                assertFalse(mCanceled);
+                assertTrue(mRunning);
+                mCanceled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // This should only be called on an animation that has been started and not
+                // yet ended
+                assertTrue(mRunning);
+                mRunning = false;
+                super.onAnimationEnd(animation);
+            }
+        };
+
+        mAnimator.addListener(mListener);
+        mAnimator.setDuration(ANIM_DURATION);
+
+        mFuture = new FutureWaiter();
+
+        mRunning = false;
+        mCanceled = false;
+    }
+
+    /**
+     * Verify that calling cancel on an unstarted animator does nothing.
+     */
+    @UiThreadTest
+    @SmallTest
+    public void testCancel() throws Exception {
+        mAnimator.cancel();
+    }
+
+    /**
+     * Verify that calling cancel on a started animator does the right thing.
+     */
+    @UiThreadTest
+    @SmallTest
+    public void testStartCancel() throws Exception {
+        mRunning = true;
+        mAnimator.start();
+        mAnimator.cancel();
+    }
+
+    /**
+     * Same as testStartCancel, but with a startDelayed animator
+     */
+    @UiThreadTest
+    @SmallTest
+    public void testStartDelayedCancel() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        mRunning = true;
+        mAnimator.start();
+        mAnimator.cancel();
+    }
+
+    /**
+     * Verify that canceling an animator that is playing does the right thing.
+     */
+    @MediumTest
+    public void testPlayingCancel() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Handler handler = new Handler();
+                    mAnimator.addListener(mFutureListener);
+                    mRunning = true;
+                    mAnimator.start();
+                    handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION);
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get();
+    }
+
+    /**
+     * Same as testPlayingCancel, but with a startDelayed animator
+     */
+    @MediumTest
+    public void testPlayingDelayedCancel() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Handler handler = new Handler();
+                    mAnimator.addListener(mFutureListener);
+                    mRunning = true;
+                    mAnimator.start();
+                    handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION);
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get();
+    }
+
+    /**
+     * Verifies that canceling a started animation after it has already been canceled
+     * does nothing.
+     */
+    @MediumTest
+    public void testStartDoubleCancel() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.cancel();
+                    mAnimator.cancel();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get();
+    }
+
+    /**
+     * Same as testStartDoubleCancel, but with a startDelayed animator
+     */
+    @MediumTest
+    public void testStartDelayedDoubleCancel() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.cancel();
+                    mAnimator.cancel();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get();
+    }
+
+
+}
diff --git a/core/tests/coretests/src/android/animation/FutureWaiter.java b/core/tests/coretests/src/android/animation/FutureWaiter.java
new file mode 100644
index 0000000..320a1c2
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/FutureWaiter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import com.google.common.util.concurrent.AbstractFuture;
+
+/**
+ * Simple extension of {@link com.google.common.util.concurrent.AbstractFuture} which exposes a new
+ * release() method which calls the protected
+ * {@link com.google.common.util.concurrent.AbstractFuture#set(Object)} method internally. It
+ * also exposes the protected {@link AbstractFuture#setException(Throwable)} method.
+ */
+public class FutureWaiter extends AbstractFuture<Void> {
+
+    /**
+     * Release the Future currently waiting on
+     * {@link com.google.common.util.concurrent.AbstractFuture#get()}.
+     */
+    public void release() {
+        super.set(null);
+    }
+
+    @Override
+    public boolean setException(Throwable throwable) {
+        return super.setException(throwable);
+    }
+}
diff --git a/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
new file mode 100644
index 0000000..606a939
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import android.widget.Button;
+import com.android.frameworks.coretests.R;
+
+/**
+ * Listener tests for ObjectAnimator.
+ */
+public class ObjectAnimatorEventsTest extends EventsTest {
+
+    @Override
+    public void setUp() throws Exception {
+        final BasicAnimatorActivity activity = getActivity();
+        Button button = (Button) activity.findViewById(R.id.animatingButton);
+
+        mAnimator = ObjectAnimator.ofFloat(button, "translationX", 0, 100);
+        super.setUp();
+    }
+
+}
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
new file mode 100644
index 0000000..c25d050
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+/**
+ * Listener tests for ValueAnimator.
+ */
+public class ValueAnimatorEventsTest extends EventsTest {
+
+    @Override
+    public void setUp() throws Exception {
+        mAnimator = ValueAnimator.ofFloat(0, 1);
+        super.setUp();
+    }
+
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index 0b72c3c..9403d95 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -54,8 +54,8 @@
         // record data into narrow window to get single bucket
         stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L);
 
-        assertEquals(1, stats.bucketCount);
-        assertBucket(stats, 0, 1024L, 2048L);
+        assertEquals(1, stats.size());
+        assertValues(stats, 0, 1024L, 2048L);
     }
 
     public void testRecordEqualBuckets() throws Exception {
@@ -66,9 +66,9 @@
         final long recordStart = TEST_START + (bucketDuration / 2);
         stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L);
 
-        assertEquals(2, stats.bucketCount);
-        assertBucket(stats, 0, 512L, 64L);
-        assertBucket(stats, 1, 512L, 64L);
+        assertEquals(2, stats.size());
+        assertValues(stats, 0, 512L, 64L);
+        assertValues(stats, 1, 512L, 64L);
     }
 
     public void testRecordTouchingBuckets() throws Exception {
@@ -81,13 +81,13 @@
         final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4);
         stats.recordData(recordStart, recordEnd, 1000L, 5000L);
 
-        assertEquals(3, stats.bucketCount);
+        assertEquals(3, stats.size());
         // first bucket should have (1/20 of value)
-        assertBucket(stats, 0, 50L, 250L);
+        assertValues(stats, 0, 50L, 250L);
         // second bucket should have (15/20 of value)
-        assertBucket(stats, 1, 750L, 3750L);
+        assertValues(stats, 1, 750L, 3750L);
         // final bucket should have (4/20 of value)
-        assertBucket(stats, 2, 200L, 1000L);
+        assertValues(stats, 2, 200L, 1000L);
     }
 
     public void testRecordGapBuckets() throws Exception {
@@ -101,9 +101,9 @@
         stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 64L, 512L);
 
         // we should have two buckets, far apart from each other
-        assertEquals(2, stats.bucketCount);
-        assertBucket(stats, 0, 128L, 256L);
-        assertBucket(stats, 1, 64L, 512L);
+        assertEquals(2, stats.size());
+        assertValues(stats, 0, 128L, 256L);
+        assertValues(stats, 1, 64L, 512L);
 
         // now record something in middle, spread across two buckets
         final long middleStart = TEST_START + DAY_IN_MILLIS;
@@ -111,11 +111,11 @@
         stats.recordData(middleStart, middleEnd, 2048L, 2048L);
 
         // now should have four buckets, with new record in middle two buckets
-        assertEquals(4, stats.bucketCount);
-        assertBucket(stats, 0, 128L, 256L);
-        assertBucket(stats, 1, 1024L, 1024L);
-        assertBucket(stats, 2, 1024L, 1024L);
-        assertBucket(stats, 3, 64L, 512L);
+        assertEquals(4, stats.size());
+        assertValues(stats, 0, 128L, 256L);
+        assertValues(stats, 1, 1024L, 1024L);
+        assertValues(stats, 2, 1024L, 1024L);
+        assertValues(stats, 3, 64L, 512L);
     }
 
     public void testRecordOverlapBuckets() throws Exception {
@@ -128,14 +128,12 @@
         stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 1024L, 1024L);
 
         // should have two buckets, with some data mixed together
-        assertEquals(2, stats.bucketCount);
-        assertBucket(stats, 0, 768L, 768L);
-        assertBucket(stats, 1, 512L, 512L);
+        assertEquals(2, stats.size());
+        assertValues(stats, 0, 768L, 768L);
+        assertValues(stats, 1, 512L, 512L);
     }
 
     public void testRecordEntireGapIdentical() throws Exception {
-        final long[] total = new long[2];
-
         // first, create two separate histories far apart
         final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS);
         stats1.recordData(TEST_START, TEST_START + 2 * HOUR_IN_MILLIS, 2000L, 1000L);
@@ -150,19 +148,16 @@
         stats.recordEntireHistory(stats2);
 
         // first verify that totals match up
-        stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
-        assertTotalEquals(total, 3000L, 1500L);
+        assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 3000L, 1500L);
 
         // now inspect internal buckets
-        assertBucket(stats, 0, 1000L, 500L);
-        assertBucket(stats, 1, 1000L, 500L);
-        assertBucket(stats, 2, 500L, 250L);
-        assertBucket(stats, 3, 500L, 250L);
+        assertValues(stats, 0, 1000L, 500L);
+        assertValues(stats, 1, 1000L, 500L);
+        assertValues(stats, 2, 500L, 250L);
+        assertValues(stats, 3, 500L, 250L);
     }
 
     public void testRecordEntireOverlapVaryingBuckets() throws Exception {
-        final long[] total = new long[2];
-
         // create history just over hour bucket boundary
         final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS);
         stats1.recordData(TEST_START, TEST_START + MINUTE_IN_MILLIS * 60, 600L, 600L);
@@ -177,17 +172,16 @@
         stats.recordEntireHistory(stats2);
 
         // first verify that totals match up
-        stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
-        assertTotalEquals(total, 650L, 650L);
+        assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L);
 
         // now inspect internal buckets
-        assertBucket(stats, 0, 10L, 10L);
-        assertBucket(stats, 1, 20L, 20L);
-        assertBucket(stats, 2, 20L, 20L);
-        assertBucket(stats, 3, 20L, 20L);
-        assertBucket(stats, 4, 20L, 20L);
-        assertBucket(stats, 5, 20L, 20L);
-        assertBucket(stats, 6, 10L, 10L);
+        assertValues(stats, 0, 10L, 10L);
+        assertValues(stats, 1, 20L, 20L);
+        assertValues(stats, 2, 20L, 20L);
+        assertValues(stats, 3, 20L, 20L);
+        assertValues(stats, 4, 20L, 20L);
+        assertValues(stats, 5, 20L, 20L);
+        assertValues(stats, 6, 10L, 10L);
 
         // now combine using 15min buckets
         stats = new NetworkStatsHistory(HOUR_IN_MILLIS / 4);
@@ -195,14 +189,13 @@
         stats.recordEntireHistory(stats2);
 
         // first verify that totals match up
-        stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
-        assertTotalEquals(total, 650L, 650L);
+        assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L);
 
         // and inspect buckets
-        assertBucket(stats, 0, 200L, 200L);
-        assertBucket(stats, 1, 150L, 150L);
-        assertBucket(stats, 2, 150L, 150L);
-        assertBucket(stats, 3, 150L, 150L);
+        assertValues(stats, 0, 200L, 200L);
+        assertValues(stats, 1, 150L, 150L);
+        assertValues(stats, 2, 150L, 150L);
+        assertValues(stats, 3, 150L, 150L);
     }
 
     public void testRemove() throws Exception {
@@ -210,28 +203,28 @@
 
         // record some data across 24 buckets
         stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L);
-        assertEquals(24, stats.bucketCount);
+        assertEquals(24, stats.size());
 
         // try removing far before buckets; should be no change
         stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS);
-        assertEquals(24, stats.bucketCount);
+        assertEquals(24, stats.size());
 
         // try removing just moments into first bucket; should be no change
         // since that bucket contains data beyond the cutoff
         stats.removeBucketsBefore(TEST_START + SECOND_IN_MILLIS);
-        assertEquals(24, stats.bucketCount);
+        assertEquals(24, stats.size());
 
         // try removing single bucket
         stats.removeBucketsBefore(TEST_START + HOUR_IN_MILLIS);
-        assertEquals(23, stats.bucketCount);
+        assertEquals(23, stats.size());
 
         // try removing multiple buckets
         stats.removeBucketsBefore(TEST_START + (4 * HOUR_IN_MILLIS));
-        assertEquals(20, stats.bucketCount);
+        assertEquals(20, stats.size());
 
         // try removing all buckets
         stats.removeBucketsBefore(TEST_START + YEAR_IN_MILLIS);
-        assertEquals(0, stats.bucketCount);
+        assertEquals(0, stats.size());
     }
 
     public void testTotalData() throws Exception {
@@ -241,27 +234,20 @@
         // record uniform data across day
         stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 2400L, 4800L);
 
-        final long[] total = new long[2];
-
         // verify that total outside range is 0
-        stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, total);
-        assertTotalEquals(total, 0, 0);
+        assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, 0L, 0L);
 
         // verify total in first hour
-        stats.getTotalData(TEST_START, TEST_START + HOUR_IN_MILLIS, total);
-        assertTotalEquals(total, 100, 200);
+        assertValues(stats, TEST_START, TEST_START + HOUR_IN_MILLIS, 100L, 200L);
 
         // verify total across 1.5 hours
-        stats.getTotalData(TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), total);
-        assertTotalEquals(total, 150, 300);
+        assertValues(stats, TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), 150L, 300L);
 
         // verify total beyond end
-        stats.getTotalData(TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, total);
-        assertTotalEquals(total, 100, 200);
+        assertValues(stats, TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, 100L, 200L);
 
         // verify everything total
-        stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
-        assertTotalEquals(total, 2400, 4800);
+        assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 2400L, 4800L);
 
     }
 
@@ -293,19 +279,27 @@
 
     private static void assertConsistent(NetworkStatsHistory stats) {
         // verify timestamps are monotonic
-        for (int i = 1; i < stats.bucketCount; i++) {
-            assertTrue(stats.bucketStart[i - 1] < stats.bucketStart[i]);
+        long lastStart = Long.MIN_VALUE;
+        NetworkStatsHistory.Entry entry = null;
+        for (int i = 0; i < stats.size(); i++) {
+            entry = stats.getValues(i, entry);
+            assertTrue(lastStart < entry.bucketStart);
+            lastStart = entry.bucketStart;
         }
     }
 
-    private static void assertTotalEquals(long[] total, long rx, long tx) {
-        assertEquals("unexpected rx", rx, total[0]);
-        assertEquals("unexpected tx", tx, total[1]);
+    private static void assertValues(
+            NetworkStatsHistory stats, int index, long rxBytes, long txBytes) {
+        final NetworkStatsHistory.Entry entry = stats.getValues(index, null);
+        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
     }
 
-    private static void assertBucket(NetworkStatsHistory stats, int index, long rx, long tx) {
-        assertEquals("unexpected rx", rx, stats.rx[index]);
-        assertEquals("unexpected tx", tx, stats.tx[index]);
+    private static void assertValues(
+            NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) {
+        final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
     }
 
 }
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 3cb64c7..2434e9f 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -31,9 +31,9 @@
 
     public void testFindIndex() throws Exception {
         final NetworkStats stats = new NetworkStats(TEST_START, 3)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L)
-                .addEntry(TEST_IFACE, 102, TAG_NONE, 1024L, 1024L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L)
+                .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L);
 
         assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE));
         assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE));
@@ -44,110 +44,106 @@
     public void testAddEntryGrow() throws Exception {
         final NetworkStats stats = new NetworkStats(TEST_START, 2);
 
-        assertEquals(0, stats.size);
-        assertEquals(2, stats.iface.length);
+        assertEquals(0, stats.size());
+        assertEquals(2, stats.internalSize());
 
-        stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 2L);
-        stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L);
+        stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L);
+        stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L);
 
-        assertEquals(2, stats.size);
-        assertEquals(2, stats.iface.length);
+        assertEquals(2, stats.size());
+        assertEquals(2, stats.internalSize());
 
-        stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 4L);
-        stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 4L);
-        stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 5L);
+        stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L);
+        stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L);
+        stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L);
 
-        assertEquals(5, stats.size);
-        assertTrue(stats.iface.length >= 5);
+        assertEquals(5, stats.size());
+        assertTrue(stats.internalSize() >= 5);
 
-        assertEquals(1L, stats.rx[0]);
-        assertEquals(2L, stats.rx[1]);
-        assertEquals(3L, stats.rx[2]);
-        assertEquals(4L, stats.rx[3]);
-        assertEquals(5L, stats.rx[4]);
+        assertEntry(stats, 0, TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L);
+        assertEntry(stats, 1, TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L);
+        assertEntry(stats, 2, TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L);
+        assertEntry(stats, 3, TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L);
+        assertEntry(stats, 4, TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L);
     }
 
     public void testCombineExisting() throws Exception {
         final NetworkStats stats = new NetworkStats(TEST_START, 10);
 
-        stats.addEntry(TEST_IFACE, 1001, TAG_NONE, 512L, 256L);
-        stats.addEntry(TEST_IFACE, 1001, 0xff, 128L, 128L);
-        stats.combineEntry(TEST_IFACE, 1001, TAG_NONE, -128L, -128L);
+        stats.addValues(TEST_IFACE, 1001, TAG_NONE, 512L, 4L, 256L, 2L);
+        stats.addValues(TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L);
+        stats.combineValues(TEST_IFACE, 1001, TAG_NONE, -128L, -1L, -128L, -1L);
 
-        assertStatsEntry(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 128L);
-        assertStatsEntry(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 128L);
+        assertEntry(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 3L, 128L, 1L);
+        assertEntry(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L);
 
         // now try combining that should create row
-        stats.combineEntry(TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
-        assertStatsEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
-        stats.combineEntry(TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
-        assertStatsEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 256L);
+        stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L);
+        assertEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L);
+        stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L);
+        assertEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 2L, 256L, 2L);
     }
 
     public void testSubtractIdenticalData() throws Exception {
         final NetworkStats before = new NetworkStats(TEST_START, 2)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
 
         final NetworkStats after = new NetworkStats(TEST_START, 2)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
 
         final NetworkStats result = after.subtract(before);
 
         // identical data should result in zero delta
-        assertEquals(0, result.rx[0]);
-        assertEquals(0, result.tx[0]);
-        assertEquals(0, result.rx[1]);
-        assertEquals(0, result.tx[1]);
+        assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L);
+        assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L);
     }
 
     public void testSubtractIdenticalRows() throws Exception {
         final NetworkStats before = new NetworkStats(TEST_START, 2)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
 
         final NetworkStats after = new NetworkStats(TEST_START, 2)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1025L, 2L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 3L, 1028L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1025L, 9L, 2L, 1L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 3L, 1L, 1028L, 9L);
 
         final NetworkStats result = after.subtract(before);
 
         // expect delta between measurements
-        assertEquals(1, result.rx[0]);
-        assertEquals(2, result.tx[0]);
-        assertEquals(3, result.rx[1]);
-        assertEquals(4, result.tx[1]);
+        assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 1L, 1L, 2L, 1L);
+        assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 3L, 1L, 4L, 1L);
     }
 
     public void testSubtractNewRows() throws Exception {
         final NetworkStats before = new NetworkStats(TEST_START, 2)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
 
         final NetworkStats after = new NetworkStats(TEST_START, 3)
-                .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
-                .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L)
-                .addEntry(TEST_IFACE, 102, TAG_NONE, 1024L, 1024L);
+                .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L)
+                .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L);
 
         final NetworkStats result = after.subtract(before);
 
         // its okay to have new rows
-        assertEquals(0, result.rx[0]);
-        assertEquals(0, result.tx[0]);
-        assertEquals(0, result.rx[1]);
-        assertEquals(0, result.tx[1]);
-        assertEquals(1024, result.rx[2]);
-        assertEquals(1024, result.tx[2]);
+        assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L);
+        assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L);
+        assertEntry(result, 2, TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L);
     }
 
-    private static void assertStatsEntry(
-            NetworkStats stats, int i, String iface, int uid, int tag, long rx, long tx) {
-        assertEquals(iface, stats.iface[i]);
-        assertEquals(uid, stats.uid[i]);
-        assertEquals(tag, stats.tag[i]);
-        assertEquals(rx, stats.rx[i]);
-        assertEquals(tx, stats.tx[i]);
+    private static void assertEntry(NetworkStats stats, int index, String iface, int uid, int tag,
+            long rxBytes, long rxPackets, long txBytes, long txPackets) {
+        final NetworkStats.Entry entry = stats.getValues(index, null);
+        assertEquals(iface, entry.iface);
+        assertEquals(uid, entry.uid);
+        assertEquals(tag, entry.tag);
+        assertEquals(rxBytes, entry.rxBytes);
+        assertEquals(rxPackets, entry.rxPackets);
+        assertEquals(txBytes, entry.txBytes);
+        assertEquals(txPackets, entry.txPackets);
     }
 
 }
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index e3cd44f..fd417cb 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -24,13 +24,8 @@
 LOCAL_SHARED_LIBRARIES := \
     libmedia \
     libutils \
-    libbinder
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+    libbinder \
+    libdl
 
 LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
 
diff --git a/drm/jni/Android.mk b/drm/jni/Android.mk
index 69bb48d..4a55fc0 100644
--- a/drm/jni/Android.mk
+++ b/drm/jni/Android.mk
@@ -26,13 +26,8 @@
     libutils \
     libandroid_runtime \
     libnativehelper \
-    libbinder
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+    libbinder \
+    libdl
 
 LOCAL_STATIC_LIBRARIES :=
 
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index f1526a4..c534402 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -25,13 +25,8 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libutils \
-    libbinder
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+    libbinder \
+    libdl
 
 LOCAL_STATIC_LIBRARIES := \
     libdrmframeworkcommon
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
index be18b64..d0d1439 100644
--- a/drm/libdrmframework/plugins/passthru/Android.mk
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -24,14 +24,8 @@
 LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
 
 LOCAL_SHARED_LIBRARIES := \
-    libutils
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
+    libutils \
+    libdl
 
 
 LOCAL_C_INCLUDES += \
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 6254192..12e5ada 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -155,6 +155,14 @@
         }
     }
 
+
+    private int getIDSafe() {
+        if (mAdaptedAllocation != null) {
+            return mAdaptedAllocation.getID();
+        }
+        return getID();
+    }
+
     private void updateCacheInfo(Type t) {
         mCurrentDimX = t.getX();
         mCurrentDimY = t.getY();
@@ -262,7 +270,7 @@
             throw new RSIllegalArgumentException("Source must be exactly one usage type.");
         }
         mRS.validate();
-        mRS.nAllocationSyncAll(getID(), srcLocation);
+        mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
     }
 
     public void copyFrom(BaseObj[] d) {
@@ -480,7 +488,7 @@
                                                " does not match component size " + eSize + ".");
         }
 
-        mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD,
+        mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
                                      component_number, data, data.length);
     }
 
@@ -527,7 +535,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
     }
     /**
      * Copy part of an allocation from an array.  This variant is
@@ -541,7 +549,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 2, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
     }
     /**
      * Copy part of an allocation from an array.  This variant is
@@ -555,7 +563,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
     }
     /**
      * Copy part of an allocation from an array.  This variant is
@@ -569,7 +577,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
     }
 
     /**
@@ -638,7 +646,7 @@
      *          be copied.
      */
     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
-        mRS.nAllocationData2D(getID(), off, 0,
+        mRS.nAllocationData2D(getIDSafe(), off, 0,
                               mSelectedLOD, mSelectedFace.mID,
                               count, 1, data.getID(), dataOff, 0,
                               data.mSelectedLOD, data.mSelectedFace.mID);
@@ -674,28 +682,28 @@
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
                               w, h, data, data.length);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
                               w, h, data, data.length * 2);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
                               w, h, data, data.length * 4);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
                               w, h, data, data.length * 4);
     }
 
@@ -715,7 +723,7 @@
                                 Allocation data, int dataXoff, int dataYoff) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff,
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
                               mSelectedLOD, mSelectedFace.mID,
                               w, h, data.getID(), dataXoff, dataYoff,
                               data.mSelectedLOD, data.mSelectedFace.mID);
@@ -734,10 +742,16 @@
         mRS.validate();
         validateBitmapFormat(data);
         validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
     }
 
 
+    /**
+     * Copy from the Allocation into a Bitmap.  The bitmap must
+     * match the dimensions of the Allocation.
+     *
+     * @param b The bitmap to be set from the Allocation.
+     */
     public void copyTo(Bitmap b) {
         mRS.validate();
         validateBitmapFormat(b);
@@ -745,24 +759,52 @@
         mRS.nAllocationCopyToBitmap(getID(), b);
     }
 
+    /**
+     * Copy from the Allocation into a byte array.  The array must
+     * be at least as large as the Allocation.  The allocation must
+     * be of an 8 bit elemental type.
+     *
+     * @param d The array to be set from the Allocation.
+     */
     public void copyTo(byte[] d) {
         validateIsInt8();
         mRS.validate();
         mRS.nAllocationRead(getID(), d);
     }
 
+    /**
+     * Copy from the Allocation into a short array.  The array must
+     * be at least as large as the Allocation.  The allocation must
+     * be of an 16 bit elemental type.
+     *
+     * @param d The array to be set from the Allocation.
+     */
     public void copyTo(short[] d) {
         validateIsInt16();
         mRS.validate();
         mRS.nAllocationRead(getID(), d);
     }
 
+    /**
+     * Copy from the Allocation into a int array.  The array must be
+     * at least as large as the Allocation.  The allocation must be
+     * of an 32 bit elemental type.
+     *
+     * @param d The array to be set from the Allocation.
+     */
     public void copyTo(int[] d) {
         validateIsInt32();
         mRS.validate();
         mRS.nAllocationRead(getID(), d);
     }
 
+    /**
+     * Copy from the Allocation into a float array.  The array must
+     * be at least as large as the Allocation.  The allocation must
+     * be of an 32 bit float elemental type.
+     *
+     * @param d The array to be set from the Allocation.
+     */
     public void copyTo(float[] d) {
         validateIsFloat32();
         mRS.validate();
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index ca5246a..d38f2df 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -31,7 +31,8 @@
     }
 
     int getID() {
-        return mAdaptedAllocation.getID();
+        throw new RSInvalidStateException(
+            "This operation is not supported with adapters at this time.");
     }
 
     /**
diff --git a/graphics/jni/Android.mk b/graphics/jni/Android.mk
index 084f54a..652189f 100644
--- a/graphics/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -1,10 +1,3 @@
-
-# libRS needs libacc, which isn't 64-bit clean, and so can't be built
-# for the simulator on gHardy, and therefore libRS needs to be excluded
-# from the simulator as well, and so in turn librs_jni needs to be
-# excluded.
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -41,5 +34,3 @@
 LOCAL_REQUIRED_MODULES := libRS
 
 include $(BUILD_SHARED_LIBRARY)
-
-endif #simulator
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 6ce44fc..9db7364 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -65,6 +65,8 @@
     int dispatchDisconnect(va_list args);
     int dispatchSetBufferCount(va_list args);
     int dispatchSetBuffersGeometry(va_list args);
+    int dispatchSetBuffersDimensions(va_list args);
+    int dispatchSetBuffersFormat(va_list args);
     int dispatchSetBuffersTransform(va_list args);
     int dispatchSetBuffersTimestamp(va_list args);
     int dispatchSetCrop(va_list args);
@@ -73,7 +75,8 @@
     int connect(int api);
     int disconnect(int api);
     int setBufferCount(int bufferCount);
-    int setBuffersGeometry(int w, int h, int format);
+    int setBuffersDimensions(int w, int h);
+    int setBuffersFormat(int format);
     int setBuffersTransform(int transform);
     int setBuffersTimestamp(int64_t timestamp);
     int setCrop(Rect const* rect);
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index d310cee..cc63356 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -51,6 +51,17 @@
     // will be suppressed until media time reaches this timestamp.
     static const char *const kKeyResumeAtPTS;
 
+    // When signalling a discontinuity you can optionally
+    // signal that this is a "hard" discontinuity, i.e. the format
+    // or configuration of subsequent stream data differs from that
+    // currently active. To do so, include a non-zero int32_t value
+    // under the key "kKeyFormatChange" when issuing the DISCONTINUITY
+    // command.
+    // The new logical stream must start with proper codec initialization
+    // information for playback to continue, i.e. SPS and PPS in the case
+    // of AVC video etc.
+    static const char *const kKeyFormatChange;
+
     virtual void issueCommand(
             Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
 };
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
index 275c19f..52a3257 100644
--- a/include/media/stagefright/MetadataBufferType.h
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -17,7 +17,11 @@
 #ifndef METADATA_BUFFER_TYPE_H
 #define METADATA_BUFFER_TYPE_H
 
+#ifdef __cplusplus
+extern "C" {
 namespace android {
+#endif
+
 /*
  * MetadataBufferType defines the type of the metadata buffers that
  * can be passed to video encoder component for encoding, via Stagefright
@@ -72,6 +76,9 @@
 
 } MetadataBufferType;
 
+#ifdef __cplusplus
 }  // namespace android
+}
+#endif
 
 #endif  // METADATA_BUFFER_TYPE_H
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index dc00957..7286f92 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -20,8 +20,4 @@
 
 LOCAL_MODULE:= libcamera_client
 
-ifeq ($(TARGET_SIMULATOR),true)
-    LOCAL_LDLIBS += -lpthread
-endif
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 4070eba..ed319f5 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -32,10 +32,6 @@
 
 LOCAL_MODULE:= libgui
 
-ifeq ($(TARGET_SIMULATOR),true)
-    LOCAL_LDLIBS += -lpthread
-endif
-
 include $(BUILD_SHARED_LIBRARY)
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index b9b2310..e203035 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -254,6 +254,12 @@
     case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
         res = dispatchSetBuffersTimestamp(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
+        res = dispatchSetBuffersDimensions(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+        res = dispatchSetBuffersFormat(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -290,7 +296,22 @@
     int w = va_arg(args, int);
     int h = va_arg(args, int);
     int f = va_arg(args, int);
-    return setBuffersGeometry(w, h, f);
+    int err = setBuffersDimensions(w, h);
+    if (err != 0) {
+        return err;
+    }
+    return setBuffersFormat(f);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) {
+    int w = va_arg(args, int);
+    int h = va_arg(args, int);
+    return setBuffersDimensions(w, h);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) {
+    int f = va_arg(args, int);
+    return setBuffersFormat(f);
 }
 
 int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
@@ -390,12 +411,12 @@
     return err;
 }
 
-int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
+int SurfaceTextureClient::setBuffersDimensions(int w, int h)
 {
-    LOGV("SurfaceTextureClient::setBuffersGeometry");
+    LOGV("SurfaceTextureClient::setBuffersDimensions");
     Mutex::Autolock lock(mMutex);
 
-    if (w<0 || h<0 || format<0)
+    if (w<0 || h<0)
         return BAD_VALUE;
 
     if ((w && !h) || (!w && h))
@@ -403,7 +424,6 @@
 
     mReqWidth = w;
     mReqHeight = h;
-    mReqFormat = format;
 
     status_t err = mSurfaceTexture->setCrop(Rect(0, 0));
     LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
@@ -411,6 +431,19 @@
     return err;
 }
 
+int SurfaceTextureClient::setBuffersFormat(int format)
+{
+    LOGV("SurfaceTextureClient::setBuffersFormat");
+    Mutex::Autolock lock(mMutex);
+
+    if (format<0)
+        return BAD_VALUE;
+
+    mReqFormat = format;
+
+    return NO_ERROR;
+}
+
 int SurfaceTextureClient::setBuffersTransform(int transform)
 {
     LOGV("SurfaceTextureClient::setBuffersTransform");
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 8d3a9b5..0308af3 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -2,8 +2,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_MODULE := SurfaceTexture_test
 
 LOCAL_MODULE_TAGS := tests
@@ -36,8 +34,6 @@
 
 include $(BUILD_EXECUTABLE)
 
-endif
-
 # Include subdirectory makefiles
 # ============================================================
 
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index d9cc6b6..a8aa0c7 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -77,11 +77,6 @@
 
 LOCAL_GENERATED_SOURCES += $(GEN)
 
-# libRS needs libacc, which isn't 64-bit clean, and so can't be built
-# for the simulator on gHardy, and therefore libRS needs to be excluded
-# from the simulator as well.
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_SRC_FILES:= \
 	rsAdapter.cpp \
 	rsAllocation.cpp \
@@ -228,5 +223,3 @@
 LOCAL_LDLIBS := -lpthread
 
 include $(BUILD_HOST_STATIC_LIBRARY)
-
-endif #simulator
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index 62eb24e..bbf2836 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -269,6 +269,7 @@
 
 void rsdScriptInvokeForEach(const Context *rsc,
                             Script *s,
+                            uint32_t slot,
                             const Allocation * ain,
                             Allocation * aout,
                             const void * usr,
diff --git a/libs/rs/driver/rsdBcc.h b/libs/rs/driver/rsdBcc.h
index 62b50f4..67929bc 100644
--- a/libs/rs/driver/rsdBcc.h
+++ b/libs/rs/driver/rsdBcc.h
@@ -32,6 +32,7 @@
 
 void rsdScriptInvokeForEach(const android::renderscript::Context *rsc,
                             android::renderscript::Script *s,
+                            uint32_t slot,
                             const android::renderscript::Allocation * ain,
                             android::renderscript::Allocation * aout,
                             const void * usr,
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 2b58e9e..b77b18a 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -263,10 +263,10 @@
     const uint8_t *p = static_cast<const uint8_t *>(ptr);
     for (uint32_t i=0; i < mFieldCount; i++) {
         if (mFields[i].e->mHasReference) {
-            p = &p[mFields[i].offsetBits >> 3];
+            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
             for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
-                mFields[i].e->incRefs(p);
-                p += mFields[i].e->getSizeBytes();
+                mFields[i].e->incRefs(p2);
+                p2 += mFields[i].e->getSizeBytes();
             }
         }
     }
@@ -285,10 +285,10 @@
     const uint8_t *p = static_cast<const uint8_t *>(ptr);
     for (uint32_t i=0; i < mFieldCount; i++) {
         if (mFields[i].e->mHasReference) {
-            p = &p[mFields[i].offsetBits >> 3];
+            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
             for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
-                mFields[i].e->decRefs(p);
-                p += mFields[i].e->getSizeBytes();
+                mFields[i].e->decRefs(p2);
+                p2 += mFields[i].e->getSizeBytes();
             }
         }
     }
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index b230bb5..e8b1014 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -121,7 +121,7 @@
 
     setupGLState(rsc);
     setupScript(rsc);
-    rsc->mHal.funcs.script.invokeForEach(rsc, this, ain, aout, usr, usrBytes, sc);
+    rsc->mHal.funcs.script.invokeForEach(rsc, this, 0, ain, aout, usr, usrBytes, sc);
 }
 
 void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 928dca5..6a4537b 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -70,6 +70,7 @@
         int (*invokeRoot)(const Context *rsc, Script *s);
         void (*invokeForEach)(const Context *rsc,
                               Script *s,
+                              uint32_t slot,
                               const Allocation * ain,
                               Allocation * aout,
                               const void * usr,
diff --git a/libs/storage/Android.mk b/libs/storage/Android.mk
index 1e52fa4..b42c34f 100644
--- a/libs/storage/Android.mk
+++ b/libs/storage/Android.mk
@@ -13,8 +13,4 @@
 
 LOCAL_MODULE:= libstorage
 
-ifeq ($(TARGET_SIMULATOR),true)
-    LOCAL_LDLIBS += -lpthread
-endif
-
 include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index 267e3edf..5fca1ce 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -7,8 +7,4 @@
 
 LOCAL_MODULE:= libsurfaceflinger_client
 
-ifeq ($(TARGET_SIMULATOR),true)
-    LOCAL_LDLIBS += -lpthread
-endif
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 427bbba..fbabfc4 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -68,10 +68,6 @@
 
 LOCAL_MODULE:= libui
 
-ifeq ($(TARGET_SIMULATOR),true)
-    LOCAL_LDLIBS += -lpthread
-endif
-
 include $(BUILD_SHARED_LIBRARY)
 
 
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 4393504..9c10c75 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -299,6 +299,7 @@
 {
     switch (operation) {
         case NATIVE_WINDOW_SET_USAGE:
+        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
         case NATIVE_WINDOW_CONNECT:
         case NATIVE_WINDOW_DISCONNECT:
             break;
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index e231971..693a32a 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -2,8 +2,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 # Build the unit tests.
 test_src_files := \
     InputChannel_test.cpp \
@@ -48,5 +46,3 @@
 
 # Build the manual test programs.
 include $(call all-subdir-makefiles)
-
-endif
\ No newline at end of file
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 774e8c9..f633357 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -103,17 +103,14 @@
 	liblog \
 	libcutils
 
-ifneq ($(TARGET_SIMULATOR),true)
 ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
 # This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp
 LOCAL_SHARED_LIBRARIES += libdl
 endif # linux-x86
-endif # sim
 
 LOCAL_MODULE:= libutils
 include $(BUILD_SHARED_LIBRARY)
 
-ifneq ($(TARGET_SIMULATOR),true)
 ifeq ($(TARGET_OS),linux)
 include $(CLEAR_VARS)
 LOCAL_C_INCLUDES += external/zlib external/icu4c/common
@@ -122,7 +119,6 @@
 LOCAL_SRC_FILES := $(commonSources) BackupData.cpp BackupHelpers.cpp
 include $(BUILD_STATIC_LIBRARY)
 endif
-endif
 
 
 # Include subdirectory makefiles
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index 87ad98e..8726a53 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -2,8 +2,6 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 # Build the unit tests.
 test_src_files := \
 	BlobCache_test.cpp \
@@ -43,5 +41,3 @@
     $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
     $(eval include $(BUILD_EXECUTABLE)) \
 )
-
-endif
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 0133cf6..f561cc0 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -16,18 +16,13 @@
 
 package android.mtp;
 
-import android.util.Log;
-
 /**
  * Java wrapper for MTP/PTP support as USB responder.
  * {@hide}
  */
-public class MtpServer {
+public class MtpServer implements Runnable {
 
-    private final Object mLock = new Object();
-    private boolean mStarted;
-
-    private static final String TAG = "MtpServer";
+    private int mNativeContext; // accessed by native methods
 
     static {
         System.loadLibrary("media_jni");
@@ -38,19 +33,14 @@
     }
 
     public void start() {
-        synchronized (mLock) {
-            native_start();
-            mStarted = true;
-        }
+        Thread thread = new Thread(this, "MtpServer");
+        thread.start();
     }
 
-    public void stop() {
-        synchronized (mLock) {
-            if (mStarted) {
-                native_stop();
-                mStarted = false;
-            }
-        }
+    @Override
+    public void run() {
+        native_run();
+        native_cleanup();
     }
 
     public void sendObjectAdded(int handle) {
@@ -70,8 +60,8 @@
     }
 
     private native final void native_setup(MtpDatabase database, boolean usePtp);
-    private native final void native_start();
-    private native final void native_stop();
+    private native final void native_run();
+    private native final void native_cleanup();
     private native final void native_send_object_added(int handle);
     private native final void native_send_object_removed(int handle);
     private native final void native_add_storage(MtpStorage storage);
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 446b630..107db08 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -22,13 +22,8 @@
 #include <limits.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <sys/ioctl.h>
 #include <utils/threads.h>
 
-#ifdef HAVE_ANDROID_OS
-#include <linux/usb/f_mtp.h>
-#endif
-
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
@@ -39,8 +34,8 @@
 
 using namespace android;
 
-// MtpStorage class
-jclass clazz_MtpStorage;
+// MtpServer fields
+static jfieldID field_MtpServer_nativeContext;
 
 // MtpStorage fields
 static jfieldID field_MtpStorage_storageId;
@@ -57,173 +52,78 @@
 // in android_mtp_MtpDatabase.cpp
 extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
 
-// ----------------------------------------------------------------------------
-
-#ifdef HAVE_ANDROID_OS
-
-static bool ExceptionCheck(void* env)
-{
-    return ((JNIEnv *)env)->ExceptionCheck();
+static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
+    return (MtpServer*)env->GetIntField(thiz, field_MtpServer_nativeContext);
 }
 
-class MtpThread : public Thread {
-private:
-    MtpDatabase*    mDatabase;
-    bool            mPtp;
-    MtpServer*      mServer;
-    MtpStorageList  mStorageList;
-    int             mFd;
-
-public:
-    MtpThread(MtpDatabase* database, bool usePtp)
-        :   mDatabase(database),
-            mPtp(usePtp),
-            mServer(NULL),
-            mFd(-1)
-    {
-    }
-
-    virtual ~MtpThread() {
-    }
-
-    void addStorage(MtpStorage *storage) {
-        mStorageList.push(storage);
-        if (mServer)
-            mServer->addStorage(storage);
-    }
-
-    void removeStorage(MtpStorageID id) {
-        MtpStorage* storage = mServer->getStorage(id);
-        if (storage) {
-            for (size_t i = 0; i < mStorageList.size(); i++) {
-                if (mStorageList[i] == storage) {
-                    mStorageList.removeAt(i);
-                    break;
-                }
-            }
-            if (mServer)
-                mServer->removeStorage(storage);
-            delete storage;
-        }
-    }
-
-    void start() {
-        run("MtpThread");
-    }
-
-    virtual bool threadLoop() {
-        sMutex.lock();
-
-        mFd = open("/dev/mtp_usb", O_RDWR);
-        if (mFd >= 0) {
-            mServer = new MtpServer(mFd, mDatabase, mPtp, AID_MEDIA_RW, 0664, 0775);
-            for (size_t i = 0; i < mStorageList.size(); i++) {
-                mServer->addStorage(mStorageList[i]);
-            }
-        } else {
-            LOGE("could not open MTP driver, errno: %d", errno);
-        }
-
-        sMutex.unlock();
-        mServer->run();
-        sMutex.lock();
-
-        close(mFd);
-        mFd = -1;
-        delete mServer;
-        mServer = NULL;
-
-        sMutex.unlock();
-        // delay a bit before retrying to avoid excessive spin
-        if (!exitPending()) {
-            sleep(1);
-        }
-
-        return true;
-    }
-
-    void sendObjectAdded(MtpObjectHandle handle) {
-        if (mServer)
-            mServer->sendObjectAdded(handle);
-    }
-
-    void sendObjectRemoved(MtpObjectHandle handle) {
-        if (mServer)
-            mServer->sendObjectRemoved(handle);
-    }
-};
-
-// This smart pointer is necessary for preventing MtpThread from exiting too early
-static sp<MtpThread> sThread;
-
-#endif // HAVE_ANDROID_OS
-
 static void
 android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp)
 {
-#ifdef HAVE_ANDROID_OS
-    // create the thread and assign it to the smart pointer
-    sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp);
-#endif
-}
-
-static void
-android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-   sMutex.lock();
-    MtpThread *thread = sThread.get();
-    if (thread)
-        thread->start();
-    sMutex.unlock();
-#endif // HAVE_ANDROID_OS
-}
-
-static void
-android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    sMutex.lock();
-    MtpThread *thread = sThread.get();
-    if (thread) {
-        thread->requestExitAndWait();
-        sThread = NULL;
+    int fd = open("/dev/mtp_usb", O_RDWR);
+    if (fd >= 0) {
+        MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),
+                usePtp, AID_MEDIA_RW, 0664, 0775);
+        env->SetIntField(thiz, field_MtpServer_nativeContext, (int)server);
+    } else {
+        LOGE("could not open MTP driver, errno: %d", errno);
     }
-    sMutex.unlock();
-#endif
+}
+
+static void
+android_mtp_MtpServer_run(JNIEnv *env, jobject thiz)
+{
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server)
+        server->run();
+    else
+        LOGE("server is null in run");
+}
+
+static void
+android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz)
+{
+    Mutex::Autolock autoLock(sMutex);
+
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server) {
+        delete server;
+        env->SetIntField(thiz, field_MtpServer_nativeContext, 0);
+    } else {
+        LOGE("server is null in cleanup");
+    }
 }
 
 static void
 android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
 {
-#ifdef HAVE_ANDROID_OS
-    sMutex.lock();
-    MtpThread *thread = sThread.get();
-    if (thread)
-        thread->sendObjectAdded(handle);
-    sMutex.unlock();
-#endif
+    Mutex::Autolock autoLock(sMutex);
+
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server)
+        server->sendObjectAdded(handle);
+    else
+        LOGE("server is null in send_object_added");
 }
 
 static void
 android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
 {
-#ifdef HAVE_ANDROID_OS
-    sMutex.lock();
-    MtpThread *thread = sThread.get();
-    if (thread)
-        thread->sendObjectRemoved(handle);
-    sMutex.unlock();
-#endif
+    Mutex::Autolock autoLock(sMutex);
+
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server)
+        server->sendObjectRemoved(handle);
+    else
+        LOGE("server is null in send_object_removed");
 }
 
 static void
 android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
 {
-#ifdef HAVE_ANDROID_OS
-    sMutex.lock();
-    MtpThread *thread = sThread.get();
-    if (thread) {
+    Mutex::Autolock autoLock(sMutex);
+
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server) {
         jint storageID = env->GetIntField(jstorage, field_MtpStorage_storageId);
         jstring path = (jstring)env->GetObjectField(jstorage, field_MtpStorage_path);
         jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
@@ -237,7 +137,7 @@
             if (descriptionStr != NULL) {
                 MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
                         reserveSpace, removable, maxFileSize);
-                thread->addStorage(storage);
+                server->addStorage(storage);
                 env->ReleaseStringUTFChars(path, pathStr);
                 env->ReleaseStringUTFChars(description, descriptionStr);
             } else {
@@ -245,24 +145,24 @@
             }
         }
     } else {
-        LOGE("MtpThread is null in add_storage");
+        LOGE("server is null in add_storage");
     }
-    sMutex.unlock();
-#endif
 }
 
 static void
 android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
 {
-#ifdef HAVE_ANDROID_OS
-    sMutex.lock();
-    MtpThread *thread = sThread.get();
-    if (thread)
-        thread->removeStorage(storageId);
-    else
-        LOGE("MtpThread is null in remove_storage");
-    sMutex.unlock();
-#endif
+    Mutex::Autolock autoLock(sMutex);
+
+    MtpServer* server = getMtpServer(env, thiz);
+    if (server) {
+        MtpStorage* storage = server->getStorage(storageId);
+        if (storage) {
+            server->removeStorage(storage);
+            delete storage;
+        }
+    } else
+        LOGE("server is null in remove_storage");
 }
 
 // ----------------------------------------------------------------------------
@@ -270,8 +170,8 @@
 static JNINativeMethod gMethods[] = {
     {"native_setup",                "(Landroid/mtp/MtpDatabase;Z)V",
                                             (void *)android_mtp_MtpServer_setup},
-    {"native_start",                "()V",  (void *)android_mtp_MtpServer_start},
-    {"native_stop",                 "()V",  (void *)android_mtp_MtpServer_stop},
+    {"native_run",                  "()V",  (void *)android_mtp_MtpServer_run},
+    {"native_cleanup",              "()V",  (void *)android_mtp_MtpServer_cleanup},
     {"native_send_object_added",    "(I)V", (void *)android_mtp_MtpServer_send_object_added},
     {"native_send_object_removed",  "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
     {"native_add_storage",          "(Landroid/mtp/MtpStorage;)V",
@@ -320,13 +220,17 @@
         LOGE("Can't find MtpStorage.mMaxFileSize");
         return -1;
     }
-    clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
 
     clazz = env->FindClass("android/mtp/MtpServer");
     if (clazz == NULL) {
         LOGE("Can't find android/mtp/MtpServer");
         return -1;
     }
+    field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (field_MtpServer_nativeContext == NULL) {
+        LOGE("Can't find MtpServer.mNativeContext");
+        return -1;
+    }
 
     return AndroidRuntime::registerNativeMethods(env,
                 "android/mtp/MtpServer", gMethods, NELEM(gMethods));
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
index 20f58e5..26265ae 100644
--- a/media/libeffects/factory/Android.mk
+++ b/media/libeffects/factory/Android.mk
@@ -12,14 +12,6 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE:= libeffects
 
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
 LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-LOCAL_C_INCLUDES := \
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index a3e76d9..a9689bc 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -130,10 +130,43 @@
     return ret;
 }
 
+int Effect_ProcessReverse(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    if ((*fx->subItfe)->process_reverse != NULL) {
+        ret = (*fx->subItfe)->process_reverse(fx->subItfe, inBuffer, outBuffer);
+    } else {
+        ret = -ENOSYS;
+    }
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+
 const struct effect_interface_s gInterface = {
         Effect_Process,
         Effect_Command,
-        Effect_GetDescriptor
+        Effect_GetDescriptor,
+        NULL
+};
+
+const struct effect_interface_s gInterfaceWithReverse = {
+        Effect_Process,
+        Effect_Command,
+        Effect_GetDescriptor,
+        Effect_ProcessReverse
 };
 
 /////////////////////////////////////////////////
@@ -266,7 +299,13 @@
     // add entry to effect list
     fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
     fx->subItfe = itfe;
-    fx->itfe = (struct effect_interface_s *)&gInterface;
+    if ((*itfe)->process_reverse != NULL) {
+        fx->itfe = (struct effect_interface_s *)&gInterfaceWithReverse;
+        LOGV("EffectCreate() gInterfaceWithReverse");
+    }   else {
+        fx->itfe = (struct effect_interface_s *)&gInterface;
+        LOGV("EffectCreate() gInterface");
+    }
     fx->lib = l;
 
     e = (list_elem_t *)malloc(sizeof(list_elem_t));
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index ab13605..f097dd0 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -19,12 +19,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
      libcutils \
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_LDLIBS += -ldl
-else
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+     libdl
 
 
 LOCAL_C_INCLUDES += \
@@ -54,12 +49,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
      libcutils \
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_LDLIBS += -ldl
-else
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+     libdl
 
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/Reverb \
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 21c451f..efa1c45 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -3231,7 +3231,8 @@
 const struct effect_interface_s gLvmEffectInterface = {
     Effect_process,
     Effect_command,
-    Effect_getDescriptor
+    Effect_getDescriptor,
+    NULL,
 };    /* end gLvmEffectInterface */
 
 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 2727375..663f8ff 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -2134,7 +2134,8 @@
 const struct effect_interface_s gReverbInterface = {
     Reverb_process,
     Reverb_command,
-    Reverb_getDescriptor
+    Reverb_getDescriptor,
+    NULL,
 };    /* end gReverbInterface */
 
 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
index c2ffce5..b22ebec 100644
--- a/media/libeffects/testlibs/EffectEqualizer.cpp
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -736,7 +736,8 @@
 const struct effect_interface_s gEqualizerInterface = {
         Equalizer_process,
         Equalizer_command,
-        Equalizer_getDescriptor
+        Equalizer_getDescriptor,
+        NULL
 };
 
 
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
index 02762c9..405f908 100644
--- a/media/libeffects/testlibs/EffectReverb.c
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -27,7 +27,8 @@
 const struct effect_interface_s gReverbInterface = {
         Reverb_Process,
         Reverb_Command,
-        Reverb_GetDescriptor
+        Reverb_GetDescriptor,
+        NULL
 };
 
 // Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index dff585f..2160177 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -9,19 +9,12 @@
 LOCAL_CFLAGS+= -O2
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils
+	libcutils \
+	libdl
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
 LOCAL_MODULE:= libvisualizer
 
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, graphics corecg) \
 	system/media/audio_effects/include
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index aeebd4d..3c3af8f 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -450,7 +450,8 @@
 const struct effect_interface_s gVisualizerInterface = {
         Visualizer_process,
         Visualizer_command,
-        Visualizer_getDescriptor
+        Visualizer_getDescriptor,
+        NULL,
 };
 
 
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index f7c54fa..7af4a87 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -49,20 +49,12 @@
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
         libcamera_client libstagefright_foundation \
-        libgui
+        libgui libdl
 
 LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper
 
 LOCAL_MODULE:= libmedia
 
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
 LOCAL_C_INCLUDES := \
     $(JNI_H_INCLUDE) \
     $(call include-path-for, graphics corecg) \
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index c14ee82..b311f35 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -29,6 +29,9 @@
 // static
 const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
 
+// static
+const char *const IStreamListener::kKeyFormatChange = "format-change";
+
 enum {
     // IStreamSource
     SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index fadad285..ec7d8a0 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -16,10 +16,6 @@
     StagefrightPlayer.cpp       \
     StagefrightRecorder.cpp
 
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
 LOCAL_SHARED_LIBRARIES :=     		\
 	libcutils             			\
 	libutils              			\
@@ -32,16 +28,13 @@
 	libstagefright        			\
 	libstagefright_omx    			\
 	libstagefright_foundation       \
-	libgui
+	libgui                          \
+	libdl
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_rtsp                     \
         libstagefright_nuplayer                 \
 
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
 LOCAL_C_INCLUDES :=                                                 \
 	$(JNI_H_INCLUDE)                                                \
 	$(call include-path-for, graphics corecg)                       \
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index bbc8a6e..a6a3a18 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -63,8 +63,17 @@
             mEOS = true;
             break;
         } else if (n == INFO_DISCONTINUITY) {
-            mTSParser->signalDiscontinuity(
-                    ATSParser::DISCONTINUITY_SEEK, extra);
+            ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK;
+
+            int32_t formatChange;
+            if (extra != NULL
+                    && extra->findInt32(
+                        IStreamListener::kKeyFormatChange, &formatChange)
+                    && formatChange != 0) {
+                type = ATSParser::DISCONTINUITY_FORMATCHANGE;
+            }
+
+            mTSParser->signalDiscontinuity(type, extra);
         } else if (n < 0) {
             CHECK_EQ(n, -EWOULDBLOCK);
             break;
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 8c4b274..7b3b95b 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -159,10 +159,8 @@
         libchromium_net         \
         libwebcore              \
 
-ifneq ($(TARGET_SIMULATOR),true)
 LOCAL_SHARED_LIBRARIES += libstlport
 include external/stlport/libstlport.mk
-endif
 
 LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
 
@@ -175,20 +173,7 @@
         libstagefright_enc_common \
         libstagefright_avc_common \
         libstagefright_foundation \
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-        LOCAL_LDLIBS += -lpthread -ldl
-        LOCAL_SHARED_LIBRARIES += libdvm
-        LOCAL_CPPFLAGS += -DANDROID_SIMULATOR
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-        LOCAL_LDLIBS += -lpthread
-endif
+        libdl
 
 LOCAL_CFLAGS += -Wno-multichar
 
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
old mode 100644
new mode 100755
index c7e7ced..1bc2fb9
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -103,6 +103,10 @@
        return OMX_COLOR_Format16bitRGB565;
     }
 
+    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
+       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
+    }
+
     LOGE("Uknown color format (%s), please add it to "
          "CameraSource::getColorFormat", colorFormat);
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
old mode 100644
new mode 100755
index eaad2c3..8c9ff87
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1715,7 +1715,10 @@
             return ERROR_MALFORMED;
         }
     }
-
+// FIXME:
+// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
+// and remove #if 0
+#if 0
     {
         // Check on the profiles
         // These profiles requires additional parameter set extensions
@@ -1725,7 +1728,7 @@
             return BAD_VALUE;
         }
     }
-
+#endif
     return OK;
 }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
old mode 100644
new mode 100755
index 06363ee..3b05752
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -218,18 +218,21 @@
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
     { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
+    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.encoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
+    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.encoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
+    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.H264E" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
@@ -393,7 +396,17 @@
     if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.DECODER")) {
         quirks |= kRequiresAllocateBufferOnInputPorts;
         quirks |= kRequiresAllocateBufferOnOutputPorts;
-    } else if (!strncmp(componentName, "OMX.TI.", 7)) {
+    }
+
+    // FIXME:
+    // Remove the quirks after the work is done.
+    else if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.MPEG4E") ||
+             !strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.H264E")) {
+
+        quirks |= kRequiresAllocateBufferOnInputPorts;
+        quirks |= kRequiresAllocateBufferOnOutputPorts;
+    }
+    else if (!strncmp(componentName, "OMX.TI.", 7)) {
         // Apparently I must not use OMX_UseBuffer on either input or
         // output ports on any of the TI components or quote:
         // "(I) may have unexpected problem (sic) which can be timing related
@@ -887,6 +900,7 @@
 
         case OMX_COLOR_FormatYUV420Planar:
         case OMX_COLOR_FormatYUV420SemiPlanar:
+        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
             return (width * height * 3) / 2;
 
         default:
@@ -910,6 +924,7 @@
         }
     }
 
+
     // Check whether the target color format is supported.
     return isColorFormatSupported(*colorFormat, kPortIndexInput);
 }
@@ -1032,6 +1047,11 @@
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
     video_def->xFramerate = 0;      // No need for output port
+    // FIXME:
+    // Revmoe this workaround after work is done.
+    if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
+        video_def->xFramerate = (frameRate << 16);
+    }
     video_def->nBitrate = bitRate;  // Q16 format
     video_def->eCompressionFormat = compressionFormat;
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
@@ -1304,6 +1324,12 @@
     h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
     h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
 
+    // FIXME:
+    // Remove the workaround after the work in done.
+    if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
+        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
+    }
+
     if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
         h264type.nSliceHeaderSpacing = 0;
         h264type.bUseHadamard = OMX_TRUE;
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
index 80b2478..6573e3c 100644
--- a/media/libstagefright/chromium_http/Android.mk
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -15,10 +15,8 @@
 
 LOCAL_CFLAGS += -Wno-multichar
 
-ifneq ($(TARGET_SIMULATOR),true)
 LOCAL_SHARED_LIBRARIES += libstlport
 include external/stlport/libstlport.mk
-endif
 
 LOCAL_MODULE:= libstagefright_chromium_http
 
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 08ad6f3..d844f3d 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -23,14 +23,7 @@
         libui                           \
         libcutils                       \
         libstagefright_foundation       \
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-        LOCAL_LDLIBS += -lpthread -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+        libdl
 
 LOCAL_MODULE:= libstagefright_omx
 
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index c25285e..e590bab 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -16,8 +16,6 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=                                       \
@@ -45,8 +43,6 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-endif
-
 ifeq ($(HOST_OS),linux)
 
 include $(CLEAR_VARS)
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 9085f10..4047e2e 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -237,6 +237,8 @@
 
     if (mSessionOpen)
         mDatabase->sessionEnded();
+    close(fd);
+    mFD = -1;
 }
 
 void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 32d1a23..3f547fd 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -88,7 +88,7 @@
  * well as how many bits are allocated to each channel. Therefore, the first thing
  * GLSurfaceView has to do when starting to render is choose what EGLConfig to use.
  * <p>
- * By default GLSurfaceView chooses a EGLConfig that has an RGB_656 pixel format,
+ * By default GLSurfaceView chooses a EGLConfig that has an RGB_565 pixel format,
  * with at least a 16-bit depth buffer and no stencil.
  * <p>
  * If you would prefer a different EGLConfig
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index b5c018f..15e58f2 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -38,15 +38,13 @@
     LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
 
-ifneq ($(TARGET_SIMULATOR),true)
-    # we need to access the private Bionic header <bionic_tls.h>
-    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
-    # behavior from the bionic Android.mk file
-    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
-        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-    endif
-    LOCAL_C_INCLUDES += bionic/libc/private
+# we need to access the private Bionic header <bionic_tls.h>
+# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+# behavior from the bionic Android.mk file
+ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
 LOCAL_MODULE:= libGLES_android
diff --git a/opengl/libagl2/Android.mk b/opengl/libagl2/Android.mk
index 564932f..b442a2d 100644
--- a/opengl/libagl2/Android.mk
+++ b/opengl/libagl2/Android.mk
@@ -39,15 +39,13 @@
     LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
 
-ifneq ($(TARGET_SIMULATOR),true)
-    # we need to access the private Bionic header <bionic_tls.h>
-    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
-    # behavior from the bionic Android.mk file
-    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
-        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-    endif
-    LOCAL_C_INCLUDES += bionic/libc/private
+# we need to access the private Bionic header <bionic_tls.h>
+# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+# behavior from the bionic Android.mk file
+ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
 #replace libagl for now
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index ff45edc..3e66a13 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -21,18 +21,14 @@
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libEGL
 LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
-# needed on sim build because of weird logging issues
-ifeq ($(TARGET_SIMULATOR),true)
-else
-    LOCAL_SHARED_LIBRARIES += libdl
-    # Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to
-    # select the appropriate TLS codepath
-    ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
-        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-    endif
-    # we need to access the private Bionic header <bionic_tls.h>
-    LOCAL_C_INCLUDES += bionic/libc/private
+LOCAL_SHARED_LIBRARIES += libdl
+# Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to
+# select the appropriate TLS codepath
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
+# we need to access the private Bionic header <bionic_tls.h>
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -81,16 +77,12 @@
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libGLESv1_CM
 
-# needed on sim build because of weird logging issues
-ifeq ($(TARGET_SIMULATOR),true)
-else
-    LOCAL_SHARED_LIBRARIES += libdl
-    # we need to access the private Bionic header <bionic_tls.h>
-    ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
-        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-    endif
-    LOCAL_C_INCLUDES += bionic/libc/private
+LOCAL_SHARED_LIBRARIES += libdl
+# we need to access the private Bionic header <bionic_tls.h>
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -117,16 +109,12 @@
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libGLESv2
 
-# needed on sim build because of weird logging issues
-ifeq ($(TARGET_SIMULATOR),true)
-else
-    LOCAL_SHARED_LIBRARIES += libdl
-    # we need to access the private Bionic header <bionic_tls.h>
-    ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
-        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-    endif
-    LOCAL_C_INCLUDES += bionic/libc/private
+LOCAL_SHARED_LIBRARIES += libdl
+# we need to access the private Bionic header <bionic_tls.h>
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index b11db32..ddad2d3 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -31,6 +31,7 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
+#include <utils/CallStack.h>
 #include <utils/String8.h>
 
 #include "egldefs.h"
@@ -147,6 +148,10 @@
     if (egl_tls_t::logNoContextCall()) {
         LOGE("call to OpenGL ES API with no current context "
              "(logged once per thread)");
+        LOGE("call stack before error:");
+        CallStack stack;
+        stack.update();
+        stack.dump();
     }
     return 0;
 }
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 7d5d010..ba5d29a 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -367,7 +367,12 @@
         if (cnx->egl.eglGetConfigAttrib(iDpy,
                 iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
             if (format != 0) {
-                native_window_set_buffers_geometry(window, 0, 0, format);
+                int err = native_window_set_buffers_format(window, format);
+                if (err != 0) {
+                    LOGE("error setting native window pixel format: %s (%d)",
+                            strerror(-err), err);
+                    return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+                }
             }
         }
 
diff --git a/opengl/libs/GLES2_dbg/Android.mk b/opengl/libs/GLES2_dbg/Android.mk
index 9f6e68c..c2b1142 100644
--- a/opengl/libs/GLES2_dbg/Android.mk
+++ b/opengl/libs/GLES2_dbg/Android.mk
@@ -31,15 +31,13 @@
     LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
 
-ifneq ($(TARGET_SIMULATOR),true)
-    # we need to access the private Bionic header <bionic_tls.h>
-    # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
-    # behavior from the bionic Android.mk file
-    ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
-        LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-    endif
-    LOCAL_C_INCLUDES += bionic/libc/private
+# we need to access the private Bionic header <bionic_tls.h>
+# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+# behavior from the bionic Android.mk file
+ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+    LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_MODULE:= libGLESv2_dbg
 LOCAL_MODULE_TAGS := optional
diff --git a/opengl/libs/GLES2_dbg/test/Android.mk b/opengl/libs/GLES2_dbg/test/Android.mk
index 14a84b4..8708d43 100644
--- a/opengl/libs/GLES2_dbg/test/Android.mk
+++ b/opengl/libs/GLES2_dbg/test/Android.mk
@@ -27,9 +27,7 @@
 ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
     LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
 endif
-ifneq ($(TARGET_SIMULATOR),true)
-    LOCAL_C_INCLUDES += bionic/libc/private
-endif
+LOCAL_C_INCLUDES += bionic/libc/private
 
 LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/opengl/specs/EGL_ANDROID_blob_cache.txt b/opengl/specs/EGL_ANDROID_blob_cache.txt
new file mode 100644
index 0000000..55dc900
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_blob_cache.txt
@@ -0,0 +1,208 @@
+Name
+
+    ANDROID_blob_cache
+
+Name Strings
+
+    EGL_ANDROID_blob_cache
+
+Contributors
+
+    Jamie Gennis
+
+Contact
+
+    Jamie Gennis, Google Inc. (jgennis 'at' google.com)
+
+Status
+
+    Draft.
+
+Version
+
+    Version 1, April 22, 2011
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.0
+
+    This extension is written against the wording of the EGL 1.4 Specification
+
+Overview
+
+    Shader compilation and optimization has been a troublesome aspect of OpenGL
+    programming for a long time.  It can consume seconds of CPU cycles during
+    application start-up.  Additionally, state-based re-compiles done
+    internally by the drivers add an unpredictable element to application
+    performance tuning, often leading to occasional pauses in otherwise smooth
+    animations.
+
+    This extension provides a mechanism through which client API
+    implementations may cache shader binaries after they are compiled.  It may
+    then retrieve those cached shaders during subsequent executions of the same
+    program.  The management of the cache is handled by the application (or
+    middleware), allowing it to be tuned to a particular platform or
+    environment.
+
+    While the focus of this extension is on providing a persistent cache for
+    shader binaries, it may also be useful for caching other data.  This is
+    perfectly acceptable, but the guarantees provided (or lack thereof) were
+    designed around the shader use case.
+
+    Note that although this extension is written as if the application
+    implements the caching functionality, on the Android OS it is implemented
+    as part of the Android EGL module.  This extension is not exposed to
+    applications on Android, but will be used automatically in every
+    application that uses EGL if it is supported by the underlying
+    device-specific EGL implementation.
+
+New Types
+
+    /*
+     * EGLsizei is a signed integer type for representing the size of a memory
+     * buffer.
+     */
+    #include <khrplatform.h>
+    typedef khronos_ssize_t EGLsizei;
+
+    /*
+     * EGLSetBlobFunc is a pointer to an application-provided function that a
+     * client API implementation may use to insert a key/value pair into the
+     * cache.
+     */
+    typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
+        const void* value, EGLsizei valueSize)
+
+    /*
+     * EGLGetBlobFunc is a pointer to an application-provided function that a
+     * client API implementation may use to retrieve a cached value from the
+     * cache.
+     */
+    typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
+        void* value, EGLsizei valueSize)
+
+New Procedures and Functions
+
+    void eglSetBlobCacheFuncs(EGLDisplay dpy,
+                              EGLSetBlobFunc set,
+                              EGLGetBlobFunc get);
+
+New Tokens
+
+    None.
+
+Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
+
+    Add a new subsection after Section 3.8, page 50
+    (Synchronization Primitives)
+
+    "3.9 Persistent Caching
+
+    In order to facilitate persistent caching of internal client API state that
+    is slow to compute or collect, the application may specify callback
+    function pointers through which the client APIs can request data be cached
+    and retrieved.  The command
+
+        void eglSetBlobCacheFuncs(EGLDisplay dpy,
+            EGLSetBlobFunc set, EGLGetBlobFunc get);
+
+    sets the callback function pointers that client APIs associated with
+    display <dpy> can use to interact with caching functionality provided by
+    the application.  <set> points to a function that inserts a new value into
+    the cache and associates it with the given key.  <get> points to a function
+    that retrieves from the cache the value associated with a given key.  The
+    semantics of these callback functions are described in Section 3.9.1 (Cache
+    Operations).
+
+    Cache functions may only be specified once during the lifetime of an
+    EGLDisplay.  The <set> and <get> functions may be called at any time and
+    from any thread from the time at which eglSetBlobCacheFuncs is called until
+    the time that the last resource associated with <dpy> is deleted and <dpy>
+    itself is terminated.  Concurrent calls to these functions from different
+    threads is also allowed.
+
+    If eglSetBlobCacheFuncs generates an error then all client APIs must behave
+    as though eglSetBlobCacheFuncs was not called for the display <dpy>.  If
+    <set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated.  If a
+    successful eglSetBlobCacheFuncs call was already made for <dpy> and the
+    display has not since been terminated then an EGL_BAD_PARAMETER error is
+    generated.
+
+    3.9.1 Cache Operations
+
+    To insert a new binary value into the cache and associate it with a given
+    key, a client API implementation can call the application-provided callback
+    function
+
+        void (*set) (const void* key, EGLsizei keySize, const void* value,
+            EGLsizei valueSize)
+
+    <key> and <value> are pointers to the beginning of the key and value,
+    respectively, that are to be inserted.  <keySize> and <valueSize> specify
+    the size in bytes of the data pointed to by <key> and <value>,
+    respectively.
+
+    No guarantees are made as to whether a given key/value pair is present in
+    the cache after the set call.  If a different value has been associated
+    with the given key in the past then it is undefined which value, if any, is
+    associated with the key after the set call.  Note that while there are no
+    guarantees, the cache implementation should attempt to cache the most
+    recently set value for a given key.
+
+    To retrieve the binary value associated with a given key from the cache, a
+    client API implementation can call the application-provided callback
+    function
+
+        EGLsizei (*get) (const void* key, EGLsizei keySize, void* value,
+            EGLsizei valueSize)
+
+    <key> is a pointer to the beginning of the key.  <keySize> specifies the
+    size in bytes of the binary key pointed to by <key>.  If the cache contains
+    a value associated with the given key then the size of that binary value in
+    bytes is returned.  Otherwise 0 is returned.
+
+    If the cache contains a value for the given key and its size in bytes is
+    less than or equal to <valueSize> then the value is written to the memory
+    pointed to by <value>.  Otherwise nothing is written to the memory pointed
+    to by <value>.
+
+Issues
+
+    1. How should errors be handled in the callback functions?
+
+    RESOLVED: No guarantees are made about the presence of values in the cache,
+    so there should not be a need to return error information to the client API
+    implementation.  The cache implementation can simply drop a value if it
+    encounters an error during the 'set' callback.  Similarly, it can simply
+    return 0 if it encouters an error in a 'get' callback.
+
+    2. When a client API driver gets updated, that may need to invalidate
+    previously cached entries.  How can the driver handle this situation?
+
+    RESPONSE: There are a number of ways the driver can handle this situation.
+    The recommended way is to include the driver version in all cache keys.
+    That way each driver version will use a set of cache keys that are unique
+    to that version, and conflicts should never occur.  Updating the driver
+    could then leave a number of values in the cache that will never be
+    requested again.  If needed, the cache implementation can handle those
+    values in some way, but the driver does not need to take any special
+    action.
+
+    3. How much data can be stored in the cache?
+
+    RESPONSE: This is entirely dependent upon the cache implementation.
+    Presumably it will be tuned to store enough data to be useful, but not
+    enough to become problematic. :)
+
+Revision History
+
+#2 (Jamie Gennis, April 25, 2011)
+    - Swapped the order of the size and pointer arguments to the get and set
+      functions.
+
+#1 (Jamie Gennis, April 22, 2011)
+    - Initial draft.
diff --git a/opengl/specs/EGL_ANDROID_recordable.txt b/opengl/specs/EGL_ANDROID_recordable.txt
new file mode 100644
index 0000000..cf44465
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_recordable.txt
@@ -0,0 +1,113 @@
+Name
+
+    ANDROID_recordable
+
+Name Strings
+
+    EGL_ANDROID_recordable
+
+Contributors
+
+    Jamie Gennis
+
+Contact
+
+    Jamie Gennis, Google Inc. (jgennis 'at' google.com)
+
+Status
+
+    Draft.
+
+Version
+
+    Version 1, July 8, 2011
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.0
+
+    This extension is written against the wording of the EGL 1.4 Specification
+
+Overview
+
+    Android supports a number of different ANativeWindow implementations that
+    can be used to create an EGLSurface.  One implementation, which records the
+    rendered image as a video each time eglSwapBuffers gets called, may have
+    some device-specific restrictions.  Because of this, some EGLConfigs may be
+    incompatible with these ANativeWindows.  This extension introduces a new
+    boolean EGLConfig attribute that indicates whether the EGLConfig supports
+    rendering to an ANativeWindow that records images to a video.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+    None.
+
+New Tokens
+
+    Accepted by the <attribute> parameter of eglGetConfigAttrib and
+    the <attrib_list> parameter of eglChooseConfig:
+
+        EGL_RECORDABLE_ANDROID                      0xXXXX
+
+Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
+
+    Section 3.4, Configuration Management, add a row to Table 3.1.
+    
+              Attribute             Type                 Notes
+        ----------------------     -------     --------------------------
+        EGL_RECORDABLE_ANDROID     boolean     whether video recording is
+                                               supported
+
+    Section 3.4, Configuration Management, add a row to Table 3.4.
+
+              Attribute            Default     Selection  Sort   Sort
+                                               Criteria   Order  Priority
+        ----------------------  -------------  ---------  -----  --------
+        EGL_RECORDABLE_ANDROID  EGL_DONT_CARE    Exact    None
+
+    Section 3.4, Configuration Management, add a paragraph at the end of the
+    subsection titled Other EGLConfig Attribute Descriptions.
+
+        EGL_RECORDABLE_ANDROID is a boolean indicating whether the config may
+        be used to create an EGLSurface from an ANativeWindow that is a video
+        recorder as indicated by the NATIVE_WINDOW_IS_VIDEO_RECORDER query on
+        the ANativeWindow.
+
+    Section 3.4.1, Querying Configurations, change the last paragraph as follow
+
+        EGLConfigs are not sorted with respect to the parameters
+        EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_CONFORMANT,
+        EGL_LEVEL, EGL_NATIVE_RENDERABLE, EGL_MAX_SWAP_INTERVAL,
+        EGL_MIN_SWAP_INTERVAL, EGL_RENDERABLE_TYPE, EGL_SURFACE_TYPE,
+        EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RED_VALUE,
+        EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_BLUE_VALUE, and
+        EGL_RECORDABLE_ANDROID.
+
+Issues
+
+    1. Should this functionality be exposed as a new attribute or as a bit in
+    the EGL_SURFACE_TYPE bitfield?
+
+    RESOLVED: It should be a new attribute.  It does not make sense to use up a
+    bit in the limit-size bitfield for a platform-specific extension.
+
+    2. How should the new attribute affect the sorting of EGLConfigs?
+
+    RESOLVED: It should not affect sorting.  Some implementations may not have
+    any drawback associated with using a recordable EGLConfig.  Such
+    implementations should not have to double-up some of their configs to  one sort earlier than .
+    Implementations that do have drawbacks can use the existing caveat
+    mechanism to report this drawback to the client.
+
+Revision History
+
+#1 (Jamie Gennis, July 8, 2011)
+    - Initial draft.
diff --git a/opengl/specs/README b/opengl/specs/README
new file mode 100644
index 0000000..2fa2587
--- /dev/null
+++ b/opengl/specs/README
@@ -0,0 +1,12 @@
+This directory contains OpenGL ES and EGL extension specifications that have
+been or are being defined for Android.  
+
+The table below tracks usage of EGL enumerant values that have been reserved
+for use by Android extensions.
+
+     Value                       Extension
+----------------     ----------------------------------
+0x3140               EGL_ANDROID_image_native_buffer
+0x3141               (unused)
+0x3142               EGL_ANDROID_recordable
+0x3143 - 0x314F      (unused)
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
index ab5f4bd..92d7eb1 100644
--- a/opengl/tests/EGLTest/Android.mk
+++ b/opengl/tests/EGLTest/Android.mk
@@ -2,8 +2,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_MODULE := EGL_test
 
 LOCAL_MODULE_TAGS := tests
@@ -29,8 +27,6 @@
 
 include $(BUILD_EXECUTABLE)
 
-endif
-
 # Include subdirectory makefiles
 # ============================================================
 
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
index e8b6c57..5d90ff6 100644
--- a/opengl/tests/gl2_jni/Android.mk
+++ b/opengl/tests/gl2_jni/Android.mk
@@ -2,8 +2,6 @@
 # OpenGL ES JNI sample
 # This makefile builds both an activity and a shared library.
 #########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
 TOP_LOCAL_PATH:= $(call my-dir)
 
 # Build activity
@@ -47,5 +45,3 @@
 
 
 include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
index 4acd91f..3d20e72 100644
--- a/opengl/tests/gl_jni/Android.mk
+++ b/opengl/tests/gl_jni/Android.mk
@@ -2,8 +2,6 @@
 # OpenGL ES JNI sample
 # This makefile builds both an activity and a shared library.
 #########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
 TOP_LOCAL_PATH:= $(call my-dir)
 
 # Build activity
@@ -49,5 +47,3 @@
 
 
 include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gl_perfapp/Android.mk b/opengl/tests/gl_perfapp/Android.mk
index 4b79569..65e50e9 100644
--- a/opengl/tests/gl_perfapp/Android.mk
+++ b/opengl/tests/gl_perfapp/Android.mk
@@ -2,8 +2,6 @@
 # OpenGL ES Perf App
 # This makefile builds both an activity and a shared library.
 #########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
 TOP_LOCAL_PATH:= $(call my-dir)
 
 # Build activity
@@ -50,5 +48,3 @@
 
 
 include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
index f1a998a..b4b378e 100644
--- a/opengl/tests/gldual/Android.mk
+++ b/opengl/tests/gldual/Android.mk
@@ -2,8 +2,6 @@
 # OpenGL ES JNI sample
 # This makefile builds both an activity and a shared library.
 #########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
 TOP_LOCAL_PATH:= $(call my-dir)
 
 # Build activity
@@ -47,5 +45,3 @@
 
 
 include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/testPauseResume/Android.mk b/opengl/tests/testPauseResume/Android.mk
index 450473a..cf8bdc3 100644
--- a/opengl/tests/testPauseResume/Android.mk
+++ b/opengl/tests/testPauseResume/Android.mk
@@ -2,8 +2,6 @@
 # OpenGL ES JNI sample
 # This makefile builds both an activity and a shared library.
 #########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
 TOP_LOCAL_PATH:= $(call my-dir)
 
 # Build activity
@@ -18,5 +16,3 @@
 LOCAL_PACKAGE_NAME := TestEGL
 
 include $(BUILD_PACKAGE)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/testViewport/Android.mk b/opengl/tests/testViewport/Android.mk
index ab37809..9980e7d 100644
--- a/opengl/tests/testViewport/Android.mk
+++ b/opengl/tests/testViewport/Android.mk
@@ -2,8 +2,6 @@
 # OpenGL ES JNI sample
 # This makefile builds both an activity and a shared library.
 #########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
 TOP_LOCAL_PATH:= $(call my-dir)
 
 # Build activity
@@ -22,5 +20,3 @@
 LOCAL_SDK_VERSION := 8
 
 include $(BUILD_PACKAGE)
-
-endif # TARGET_SIMULATOR
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 7f6327d..dff0556 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1555,9 +1555,12 @@
             // We restore the panel if it was last open; we skip it if it
             // now is open, to avoid a race condition if the user immediately
             // opens it when we are resuming.
-            if ((st != null) && !st.isOpen && st.wasLastOpen) {
-                st.isInExpandedMode = st.wasLastExpanded;
-                openPanel(st, null);
+            if (st != null) {
+                st.applyFrozenState();
+                if (!st.isOpen && st.wasLastOpen) {
+                    st.isInExpandedMode = st.wasLastExpanded;
+                    openPanel(st, null);
+                }
             }
         }
     }
@@ -2235,6 +2238,11 @@
                 }
                 mActionModePopup = null;
             }
+
+            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+            if (st != null && st.menu != null) {
+                st.menu.close();
+            }
         }
 
         @Override
@@ -3046,46 +3054,33 @@
 
             getIconMenuView(cb); // Need this initialized to know where our offset goes
 
-            boolean init = false;
             if (expandedMenuPresenter == null) {
                 expandedMenuPresenter = new ListMenuPresenter(
                         com.android.internal.R.layout.list_menu_item_layout,
                         com.android.internal.R.style.Theme_ExpandedMenu);
                 expandedMenuPresenter.setCallback(cb);
+                expandedMenuPresenter.setId(com.android.internal.R.id.list_menu_presenter);
                 menu.addMenuPresenter(expandedMenuPresenter);
-                init = true;
             }
 
             expandedMenuPresenter.setItemIndexOffset(iconMenuPresenter.getNumActualItemsShown());
             MenuView result = expandedMenuPresenter.getMenuView(decorView);
 
-            if (init && frozenMenuState != null) {
-                expandedMenuPresenter.restoreHierarchyState(frozenMenuState);
-                // Once we initialize the expanded menu we're done with the frozen state
-                // since we will have also restored any icon menu state.
-                frozenMenuState = null;
-            }
-
             return result;
         }
 
         MenuView getIconMenuView(MenuPresenter.Callback cb) {
             if (menu == null) return null;
 
-            boolean init = false;
             if (iconMenuPresenter == null) {
                 iconMenuPresenter = new IconMenuPresenter();
                 iconMenuPresenter.setCallback(cb);
+                iconMenuPresenter.setId(com.android.internal.R.id.icon_menu_presenter);
                 menu.addMenuPresenter(iconMenuPresenter);
-                init = true;
             }
 
             MenuView result = iconMenuPresenter.getMenuView(decorView);
 
-            if (init && frozenMenuState != null) {
-                iconMenuPresenter.restoreHierarchyState(frozenMenuState);
-            }
-
             return result;
         }
 
@@ -3097,12 +3092,7 @@
 
             if (menu != null) {
                 savedState.menuState = new Bundle();
-                if (iconMenuPresenter != null) {
-                    iconMenuPresenter.saveHierarchyState(savedState.menuState);
-                }
-                if (expandedMenuPresenter != null) {
-                    expandedMenuPresenter.saveHierarchyState(savedState.menuState);
-                }
+                menu.savePresenterStates(savedState.menuState);
             }
 
             return savedState;
@@ -3127,6 +3117,13 @@
             decorView = null;
         }
 
+        void applyFrozenState() {
+            if (menu != null && frozenMenuState != null) {
+                menu.restorePresenterStates(frozenMenuState);
+                frozenMenuState = null;
+            }
+        }
+
         private static class SavedState implements Parcelable {
             int featureId;
             boolean isOpen;
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 75d24a1..6bb1f56 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -20,23 +20,12 @@
     libmedia \
     libhardware \
     libhardware_legacy \
-    libeffects
+    libeffects \
+    libdl
 
 LOCAL_STATIC_LIBRARIES := \
     libmedia_helper
 
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
 LOCAL_MODULE:= libaudioflinger
 
-ifeq ($(TARGET_SIMULATOR),true)
-    ifeq ($(HOST_OS),linux)
-        LOCAL_LDLIBS += -lrt -lpthread
-    endif
-endif
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 836c081..e36507a 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -41,10 +41,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
-ifeq ($(TARGET_SIMULATOR),true)
-    LOCAL_LDLIBS += -lpthread
-endif
-
 include $(BUILD_SHARED_LIBRARY)
 
 
diff --git a/services/input/tests/Android.mk b/services/input/tests/Android.mk
index cabbccb..d92fc74 100644
--- a/services/input/tests/Android.mk
+++ b/services/input/tests/Android.mk
@@ -2,8 +2,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 # Build the unit tests.
 test_src_files := \
     InputReader_test.cpp \
@@ -45,5 +43,3 @@
 
 # Build the manual test programs.
 include $(call all-subdir-makefiles)
-
-endif
\ No newline at end of file
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 2d55433..18d393f 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -531,10 +531,7 @@
         mImeSwitcherNotification.sound = null;
         mImeSwitcherNotification.vibrate = null;
         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
-                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        mImeSwitchPendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
         mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
                 com.android.internal.R.bool.show_ongoing_ime_switcher);
 
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index da1bf83..829df39 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -77,11 +77,15 @@
 
     /** Path to {@code /proc/uid_stat}. */
     @Deprecated
-    private final File mProcStatsUidstat;
+    private final File mStatsUid;
+    /** Path to {@code /proc/net/dev}. */
+    private final File mStatsIface;
     /** Path to {@code /proc/net/xt_qtaguid/stats}. */
-    private final File mProcStatsNetfilter;
+    private final File mStatsXtUid;
+    /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
+    private final File mStatsXtIface;
 
-    /** {@link #mProcStatsNetfilter} headers. */
+    /** {@link #mStatsXtUid} headers. */
     private static final String KEY_IFACE = "iface";
     private static final String KEY_TAG_HEX = "acct_tag_hex";
     private static final String KEY_UID = "uid_tag_int";
@@ -137,8 +141,10 @@
         mContext = context;
         mObservers = new ArrayList<INetworkManagementEventObserver>();
 
-        mProcStatsUidstat = new File(procRoot, "uid_stat");
-        mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats");
+        mStatsUid = new File(procRoot, "uid_stat");
+        mStatsIface = new File(procRoot, "net/dev");
+        mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
+        mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
 
         if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
             return;
@@ -161,9 +167,12 @@
     }
 
     // @VisibleForTesting
-    public static NetworkManagementService createForTest(Context context, File procRoot) {
+    public static NetworkManagementService createForTest(
+            Context context, File procRoot, boolean bandwidthControlEnabled) {
         // TODO: eventually connect with mock netd
-        return new NetworkManagementService(context, procRoot);
+        final NetworkManagementService service = new NetworkManagementService(context, procRoot);
+        service.mBandwidthControlEnabled = bandwidthControlEnabled;
+        return service;
     }
 
     public void systemReady() {
@@ -930,13 +939,68 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
 
-        final String[] ifaces = listInterfaces();
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), ifaces.length);
+        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+        final NetworkStats.Entry entry = new NetworkStats.Entry();
 
-        for (String iface : ifaces) {
-            final long rx = getInterfaceCounter(iface, true);
-            final long tx = getInterfaceCounter(iface, false);
-            stats.addEntry(iface, UID_ALL, TAG_NONE, rx, tx);
+        final HashSet<String> activeIfaces = Sets.newHashSet();
+        final ArrayList<String> values = Lists.newArrayList();
+
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader(mStatsIface));
+
+            // skip first two header lines
+            reader.readLine();
+            reader.readLine();
+
+            // parse remaining lines
+            String line;
+            while ((line = reader.readLine()) != null) {
+                splitLine(line, values);
+
+                try {
+                    entry.iface = values.get(0);
+                    entry.uid = UID_ALL;
+                    entry.tag = TAG_NONE;
+                    entry.rxBytes = Long.parseLong(values.get(1));
+                    entry.rxPackets = Long.parseLong(values.get(2));
+                    entry.txBytes = Long.parseLong(values.get(9));
+                    entry.txPackets = Long.parseLong(values.get(10));
+
+                    activeIfaces.add(entry.iface);
+                    stats.addValues(entry);
+                } catch (NumberFormatException e) {
+                    Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
+                }
+            }
+        } catch (IOException e) {
+            Slog.w(TAG, "problem parsing stats: " + e);
+        } finally {
+            IoUtils.closeQuietly(reader);
+        }
+
+        if (DBG) Slog.d(TAG, "recorded active stats from " + activeIfaces);
+
+        // splice in stats from any disabled ifaces
+        if (mBandwidthControlEnabled) {
+            final HashSet<String> xtIfaces = Sets.newHashSet(fileListWithoutNull(mStatsXtIface));
+            xtIfaces.removeAll(activeIfaces);
+
+            for (String iface : xtIfaces) {
+                final File ifacePath = new File(mStatsXtIface, iface);
+
+                entry.iface = iface;
+                entry.uid = UID_ALL;
+                entry.tag = TAG_NONE;
+                entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
+                entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
+                entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
+                entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
+
+                stats.addValues(entry);
+            }
+
+            if (DBG) Slog.d(TAG, "recorded stale stats from " + xtIfaces);
         }
 
         return stats;
@@ -1063,13 +1127,15 @@
      */
     private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) {
         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+        final NetworkStats.Entry entry = new NetworkStats.Entry();
+
         final ArrayList<String> keys = Lists.newArrayList();
         final ArrayList<String> values = Lists.newArrayList();
         final HashMap<String, String> parsed = Maps.newHashMap();
 
         BufferedReader reader = null;
         try {
-            reader = new BufferedReader(new FileReader(mProcStatsNetfilter));
+            reader = new BufferedReader(new FileReader(mStatsXtUid));
 
             // parse first line as header
             String line = reader.readLine();
@@ -1081,15 +1147,16 @@
                 parseLine(keys, values, parsed);
 
                 try {
-                    final String iface = parsed.get(KEY_IFACE);
-                    final int tag = NetworkManagementSocketTagger.kernelToTag(
+                    // TODO: add rxPackets/txPackets once kernel exports
+                    entry.iface = parsed.get(KEY_IFACE);
+                    entry.tag = NetworkManagementSocketTagger.kernelToTag(
                             parsed.get(KEY_TAG_HEX));
-                    final int uid = Integer.parseInt(parsed.get(KEY_UID));
-                    final long rx = Long.parseLong(parsed.get(KEY_RX));
-                    final long tx = Long.parseLong(parsed.get(KEY_TX));
+                    entry.uid = Integer.parseInt(parsed.get(KEY_UID));
+                    entry.rxBytes = Long.parseLong(parsed.get(KEY_RX));
+                    entry.txBytes = Long.parseLong(parsed.get(KEY_TX));
 
-                    if (limitUid == UID_ALL || limitUid == uid) {
-                        stats.addEntry(iface, uid, tag, rx, tx);
+                    if (limitUid == UID_ALL || limitUid == entry.uid) {
+                        stats.addValues(entry);
                     }
                 } catch (NumberFormatException e) {
                     Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
@@ -1114,19 +1181,27 @@
     private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
         final String[] knownUids;
         if (limitUid == UID_ALL) {
-            knownUids = mProcStatsUidstat.list();
+            knownUids = fileListWithoutNull(mStatsUid);
         } else {
             knownUids = new String[] { String.valueOf(limitUid) };
         }
 
         final NetworkStats stats = new NetworkStats(
                 SystemClock.elapsedRealtime(), knownUids.length);
+        final NetworkStats.Entry entry = new NetworkStats.Entry();
         for (String uid : knownUids) {
             final int uidInt = Integer.parseInt(uid);
-            final File uidPath = new File(mProcStatsUidstat, uid);
-            final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
-            final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
-            stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx);
+            final File uidPath = new File(mStatsUid, uid);
+
+            entry.iface = IFACE_ALL;
+            entry.uid = uidInt;
+            entry.tag = TAG_NONE;
+            entry.rxBytes = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
+            entry.rxPackets = readSingleLongFromFile(new File(uidPath, "tcp_rcv_pkt"));
+            entry.txBytes = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
+            entry.txPackets = readSingleLongFromFile(new File(uidPath, "tcp_snd_pkt"));
+
+            stats.addValues(entry);
         }
 
         return stats;
@@ -1197,7 +1272,7 @@
     private static void splitLine(String line, ArrayList<String> outSplit) {
         outSplit.clear();
 
-        final StringTokenizer t = new StringTokenizer(line);
+        final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:");
         while (t.hasMoreTokens()) {
             outSplit.add(t.nextToken());
         }
@@ -1232,6 +1307,15 @@
         }
     }
 
+    /**
+     * Wrapper for {@link File#list()} that returns empty array instead of
+     * {@code null}.
+     */
+    private static String[] fileListWithoutNull(File file) {
+        final String[] list = file.list();
+        return list != null ? list : new String[0];
+    }
+
     public void setDefaultInterfaceForDns(String iface) throws IllegalStateException {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 24d4dd3..b8890aa 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -515,8 +515,9 @@
                         mIface, NetworkStats.UID_ALL, NetworkStats.TAG_NONE);
 
                 if (index != -1) {
-                    incRead = stats.rx[index] - mLastRead;
-                    incWrite = stats.tx[index] - mLastWrite;
+                    final NetworkStats.Entry entry = stats.getValues(index, null);
+                    incRead = entry.rxBytes - mLastRead;
+                    incWrite = entry.txBytes - mLastWrite;
                 } else {
                     // missing iface, assume stats are 0
                     Slog.w(TAG, "unable to find stats for iface " + mIface);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d5e8730..8501163 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -208,6 +208,12 @@
     // before we decide it's never going to come up for real.
     static final int PROC_START_TIMEOUT = 10*1000;
 
+    // How long we wait for a launched process to attach to the activity manager
+    // before we decide it's never going to come up for real, when the process was
+    // started with a wrapper for instrumentation (such as Valgrind) because it
+    // could take much longer than usual.
+    static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
+
     // How long to wait after going idle before forcing apps to GC.
     static final int GC_TIMEOUT = 5*1000;
 
@@ -1950,9 +1956,13 @@
             if ("1".equals(SystemProperties.get("debug.assert"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
             }
-            int pid = Process.start("android.app.ActivityThread",
+
+            // Start the process.  It will either succeed and return a result containing
+            // the PID of the new process, or else throw a RuntimeException.
+            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                     app.processName, uid, uid, gids, debugFlags,
                     app.info.targetSdkVersion, null);
+
             BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
             synchronized (bs) {
                 if (bs.isOnBattery()) {
@@ -1960,12 +1970,12 @@
                 }
             }
             
-            EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
+            EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
                     app.processName, hostingType,
                     hostingNameStr != null ? hostingNameStr : "");
             
             if (app.persistent) {
-                Watchdog.getInstance().processStarted(app.processName, pid);
+                Watchdog.getInstance().processStarted(app.processName, startResult.pid);
             }
             
             StringBuilder buf = mStringBuilder;
@@ -1979,7 +1989,7 @@
                 buf.append(hostingNameStr);
             }
             buf.append(": pid=");
-            buf.append(pid);
+            buf.append(startResult.pid);
             buf.append(" uid=");
             buf.append(uid);
             buf.append(" gids={");
@@ -1992,21 +2002,15 @@
             }
             buf.append("}");
             Slog.i(TAG, buf.toString());
-            if (pid > 0) {
-                app.pid = pid;
-                app.removed = false;
-                synchronized (mPidsSelfLocked) {
-                    this.mPidsSelfLocked.put(pid, app);
-                    Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
-                    msg.obj = app;
-                    mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
-                }
-            } else {
-                app.pid = 0;
-                RuntimeException e = new RuntimeException(
-                        "Failure starting process " + app.processName
-                        + ": returned pid=" + pid);
-                Slog.e(TAG, e.getMessage(), e);
+            app.pid = startResult.pid;
+            app.usingWrapper = startResult.usingWrapper;
+            app.removed = false;
+            synchronized (mPidsSelfLocked) {
+                this.mPidsSelfLocked.put(startResult.pid, app);
+                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
+                msg.obj = app;
+                mHandler.sendMessageDelayed(msg, startResult.usingWrapper
+                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
             }
         } catch (RuntimeException e) {
             // XXX do better error recovery.
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 090e26b..73ffafb 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -658,12 +658,12 @@
     public long getKeyDispatchingTimeout() {
         synchronized(service) {
             ActivityRecord r = getWaitingHistoryRecordLocked();
-            if (r == null || r.app == null
-                    || r.app.instrumentationClass == null) {
-                return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
+            if (r != null && r.app != null
+                    && (r.app.instrumentationClass != null || r.app.usingWrapper)) {
+                return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
             }
-            
-            return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
+
+            return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
         }
     }
 
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 3968f66..da83e7d 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -78,6 +78,7 @@
     IInstrumentationWatcher instrumentationWatcher; // who is waiting
     Bundle instrumentationArguments;// as given to us
     ComponentName instrumentationResultClass;// copy of instrumentationClass
+    boolean usingWrapper;       // Set to true when process was launched with a wrapper attached
     BroadcastRecord curReceiver;// receiver currently running in the app
     long lastWakeTime;          // How long proc held wake lock at last check
     long lastCpuTime;           // How long proc has run CPU at last check
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 6e8f248..12c8ccf 100644
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -63,7 +63,7 @@
     private static final String TAG = "UsageStats";
     
     // Current on-disk Parcel version
-    private static final int VERSION = 1005;
+    private static final int VERSION = 1006;
 
     private static final int CHECKIN_VERSION = 4;
     
@@ -145,6 +145,8 @@
         final HashMap<String, TimeStats> mLaunchTimes
                 = new HashMap<String, TimeStats>();
         int mLaunchCount;
+        final HashMap<String, Long> mLastResumeTimes
+                = new HashMap<String, Long>();
         long mUsageTime;
         long mPausedTime;
         long mResumedTime;
@@ -160,20 +162,28 @@
             if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
                     + ", Usage time:" + mUsageTime);
             
-            final int N = in.readInt();
-            if (localLOGV) Slog.v(TAG, "Reading comps: " + N);
-            for (int i=0; i<N; i++) {
+            final int numTimeStats = in.readInt();
+            if (localLOGV) Slog.v(TAG, "Reading comps: " + numTimeStats);
+            for (int i=0; i<numTimeStats; i++) {
                 String comp = in.readString();
                 if (localLOGV) Slog.v(TAG, "Component: " + comp);
                 TimeStats times = new TimeStats(in);
                 mLaunchTimes.put(comp, times);
             }
+            final int numResumeTimes = in.readInt();
+            if (localLOGV) Slog.v(TAG, "Reading last resume times: " + numResumeTimes);
+            for (int i=0; i<numResumeTimes; i++) {
+                String comp = in.readString();
+                if (localLOGV) Slog.v(TAG, "Component: " + comp);
+                mLastResumeTimes.put(comp, in.readLong());
+            }
         }
-        
-        void updateResume(boolean launched) {
+
+        void updateResume(String comp, boolean launched) {
             if (launched) {
                 mLaunchCount ++;
             }
+            mLastResumeTimes.put(comp, System.currentTimeMillis());
             mResumedTime = SystemClock.elapsedRealtime();
         }
         
@@ -203,20 +213,29 @@
         void writeToParcel(Parcel out) {
             out.writeInt(mLaunchCount);
             out.writeLong(mUsageTime);
-            final int N = mLaunchTimes.size();
-            out.writeInt(N);
-            if (N > 0) {
+            final int numTimeStats = mLaunchTimes.size();
+            out.writeInt(numTimeStats);
+            if (numTimeStats > 0) {
                 for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
                     out.writeString(ent.getKey());
                     TimeStats times = ent.getValue();
                     times.writeToParcel(out);
                 }
             }
+            final int numResumeTimes = mLastResumeTimes.size();
+            out.writeInt(numResumeTimes);
+            if (numResumeTimes > 0) {
+                for (Map.Entry<String, Long> ent : mLastResumeTimes.entrySet()) {
+                    out.writeString(ent.getKey());
+                    out.writeLong(ent.getValue());
+                }
+            }
         }
         
         void clear() {
             mLaunchTimes.clear();
             mLaunchCount = 0;
+            mLastResumeTimes.clear();
             mUsageTime = 0;
         }
     }
@@ -546,7 +565,7 @@
                 pus = new PkgUsageStatsExtended();
                 mStats.put(pkgName, pus);
             }
-            pus.updateResume(!samePackage);
+            pus.updateResume(mLastResumedComp, !samePackage);
             if (!sameComp) {
                 pus.addLaunchCount(mLastResumedComp);
             }
@@ -624,7 +643,8 @@
             if (pus == null) {
                return null;
             }
-            return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
+            return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime,
+                    pus.mLastResumeTimes);
         }
     }
     
@@ -641,7 +661,8 @@
             int i = 0;
             for (String key: keys) {
                 PkgUsageStatsExtended pus = mStats.get(key);
-                retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime);
+                retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime,
+                        pus.mLastResumeTimes);
                 i++;
             }
             return retArr;
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 6bb7949..d7d4b03 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -221,8 +221,6 @@
     }
 
     public void interfaceLinkStateChanged(String iface, boolean up) {
-        if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
-        interfaceStatusChanged(iface, up);
     }
 
     private boolean isUsb(String iface) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index d23d0f4..d30b66b 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -405,7 +405,8 @@
             try {
                 final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
                         policy.template, start, end);
-                total = stats.rx[0] + stats.tx[0];
+                final NetworkStats.Entry entry = stats.getValues(0, null);
+                total = entry.rxBytes + entry.txBytes;
             } catch (RemoteException e) {
                 Slog.w(TAG, "problem reading summary for template " + policy.template);
                 continue;
@@ -605,7 +606,8 @@
             final long total;
             try {
                 stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
-                total = stats.rx[0] + stats.tx[0];
+                final NetworkStats.Entry entry = stats.getValues(0, null);
+                total = entry.rxBytes + entry.txBytes;
             } catch (RemoteException e) {
                 Slog.w(TAG, "problem reading summary for template " + policy.template);
                 continue;
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index b6834f6..54e94db 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -313,22 +313,29 @@
         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
 
         synchronized (mStatsLock) {
-            long rx = 0;
-            long tx = 0;
-            long[] networkTotal = new long[2];
+            // use system clock to be externally consistent
+            final long now = System.currentTimeMillis();
+
+            final NetworkStats stats = new NetworkStats(end - start, 1);
+            final NetworkStats.Entry entry = new NetworkStats.Entry();
+            NetworkStatsHistory.Entry historyEntry = null;
 
             // combine total from all interfaces that match template
             for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
                 if (templateMatches(template, ident)) {
                     final NetworkStatsHistory history = mNetworkStats.get(ident);
-                    networkTotal = history.getTotalData(start, end, networkTotal);
-                    rx += networkTotal[0];
-                    tx += networkTotal[1];
+                    historyEntry = history.getValues(start, end, now, historyEntry);
+
+                    entry.iface = IFACE_ALL;
+                    entry.uid = UID_ALL;
+                    entry.tag = TAG_NONE;
+                    entry.rxBytes = historyEntry.rxBytes;
+                    entry.txBytes = historyEntry.txBytes;
+
+                    stats.combineValues(entry);
                 }
             }
 
-            final NetworkStats stats = new NetworkStats(end - start, 1);
-            stats.addEntry(IFACE_ALL, UID_ALL, TAG_NONE, rx, tx);
             return stats;
         }
     }
@@ -341,8 +348,12 @@
         synchronized (mStatsLock) {
             ensureUidStatsLoadedLocked();
 
+            // use system clock to be externally consistent
+            final long now = System.currentTimeMillis();
+
             final NetworkStats stats = new NetworkStats(end - start, 24);
-            long[] total = new long[2];
+            final NetworkStats.Entry entry = new NetworkStats.Entry();
+            NetworkStatsHistory.Entry historyEntry = null;
 
             for (NetworkIdentitySet ident : mUidStats.keySet()) {
                 if (templateMatches(template, ident)) {
@@ -356,11 +367,16 @@
                         // other tags when requested.
                         if (tag == TAG_NONE || includeTags) {
                             final NetworkStatsHistory history = uidStats.valueAt(i);
-                            total = history.getTotalData(start, end, total);
-                            final long rx = total[0];
-                            final long tx = total[1];
-                            if (rx > 0 || tx > 0) {
-                                stats.combineEntry(IFACE_ALL, uid, tag, rx, tx);
+                            historyEntry = history.getValues(start, end, now, historyEntry);
+
+                            entry.iface = IFACE_ALL;
+                            entry.uid = uid;
+                            entry.tag = tag;
+                            entry.rxBytes = historyEntry.rxBytes;
+                            entry.txBytes = historyEntry.txBytes;
+
+                            if (entry.rxBytes > 0 || entry.txBytes > 0) {
+                                stats.combineValues(entry);
                             }
                         }
                     }
@@ -415,6 +431,7 @@
             // broadcast.
             final int uid = intent.getIntExtra(EXTRA_UID, 0);
             synchronized (mStatsLock) {
+                // TODO: perform one last stats poll for UID
                 removeUidLocked(uid);
             }
         }
@@ -512,10 +529,13 @@
         final NetworkStats persistDelta = computeStatsDelta(
                 mLastPersistNetworkSnapshot, networkSnapshot);
         final long persistThreshold = mSettings.getPersistThreshold();
+
+        NetworkStats.Entry entry = null;
         for (String iface : persistDelta.getUniqueIfaces()) {
             final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE);
-            if (forcePersist || persistDelta.rx[index] > persistThreshold
-                    || persistDelta.tx[index] > persistThreshold) {
+            entry = persistDelta.getValues(index, entry);
+            if (forcePersist || entry.rxBytes > persistThreshold
+                    || entry.txBytes > persistThreshold) {
                 writeNetworkStatsLocked();
                 if (mUidStatsLoaded) {
                     writeUidStatsLocked();
@@ -538,20 +558,19 @@
         final HashSet<String> unknownIface = Sets.newHashSet();
 
         final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot);
-        final long timeStart = currentTime - delta.elapsedRealtime;
-        for (int i = 0; i < delta.size; i++) {
-            final String iface = delta.iface[i];
-            final NetworkIdentitySet ident = mActiveIfaces.get(iface);
+        final long timeStart = currentTime - delta.getElapsedRealtime();
+
+        NetworkStats.Entry entry = null;
+        for (int i = 0; i < delta.size(); i++) {
+            entry = delta.getValues(i, entry);
+            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
             if (ident == null) {
-                unknownIface.add(iface);
+                unknownIface.add(entry.iface);
                 continue;
             }
 
-            final long rx = delta.rx[i];
-            final long tx = delta.tx[i];
-
             final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
-            history.recordData(timeStart, currentTime, rx, tx);
+            history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes);
         }
 
         // trim any history beyond max
@@ -574,22 +593,19 @@
         ensureUidStatsLoadedLocked();
 
         final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot);
-        final long timeStart = currentTime - delta.elapsedRealtime;
+        final long timeStart = currentTime - delta.getElapsedRealtime();
 
-        for (int i = 0; i < delta.size; i++) {
-            final String iface = delta.iface[i];
-            final NetworkIdentitySet ident = mActiveIfaces.get(iface);
+        NetworkStats.Entry entry = null;
+        for (int i = 0; i < delta.size(); i++) {
+            entry = delta.getValues(i, entry);
+            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
             if (ident == null) {
                 continue;
             }
 
-            final int uid = delta.uid[i];
-            final int tag = delta.tag[i];
-            final long rx = delta.rx[i];
-            final long tx = delta.tx[i];
-
-            final NetworkStatsHistory history = findOrCreateUidStatsLocked(ident, uid, tag);
-            history.recordData(timeStart, currentTime, rx, tx);
+            final NetworkStatsHistory history = findOrCreateUidStatsLocked(
+                    ident, entry.uid, entry.tag);
+            history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes);
         }
 
         // trim any history beyond max
@@ -651,7 +667,7 @@
         NetworkStatsHistory updated = null;
         if (existing == null) {
             updated = new NetworkStatsHistory(bucketDuration, 10);
-        } else if (existing.bucketDuration != bucketDuration) {
+        } else if (existing.getBucketDuration() != bucketDuration) {
             updated = new NetworkStatsHistory(
                     bucketDuration, estimateResizeBuckets(existing, bucketDuration));
             updated.recordEntireHistory(existing);
@@ -683,7 +699,7 @@
         NetworkStatsHistory updated = null;
         if (existing == null) {
             updated = new NetworkStatsHistory(bucketDuration, 10);
-        } else if (existing.bucketDuration != bucketDuration) {
+        } else if (existing.getBucketDuration() != bucketDuration) {
             updated = new NetworkStatsHistory(
                     bucketDuration, estimateResizeBuckets(existing, bucketDuration));
             updated.recordEntireHistory(existing);
@@ -1003,7 +1019,7 @@
     }
 
     private static int estimateResizeBuckets(NetworkStatsHistory existing, long newBucketDuration) {
-        return (int) (existing.bucketCount * existing.bucketDuration / newBucketDuration);
+        return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration);
     }
 
     // @VisibleForTesting
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 1ab570a..3139798 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -138,12 +138,9 @@
 
         // create a thread for our Handler
         HandlerThread thread = new HandlerThread("UsbDeviceManager",
-                Process.THREAD_PRIORITY_BACKGROUND) {
-            protected void onLooperPrepared() {
-                mHandler = new UsbHandler();
-            }
-        };
+                Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
+        mHandler = new UsbHandler(thread.getLooper());
     }
 
     public void systemReady() {
@@ -249,21 +246,21 @@
         private static final int NOTIFICATION_INSTALLER = 3;
         private static final int NOTIFICATION_ADB = 4;
 
-        public UsbHandler() {
+        public UsbHandler(Looper looper) {
+            super(looper);
             try {
+                // persist.sys.usb.config should never be unset.  But if it is, set it to "adb"
+                // so we have a chance of debugging what happened.
+                mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb");
                 // sanity check the sys.usb.config system property
                 // this may be necessary if we crashed while switching USB configurations
                 String config = SystemProperties.get("sys.usb.config", "none");
-                if (config.equals("none")) {
-                    String persistConfig = SystemProperties.get("persist.sys.usb.config", "none");
-                    Slog.w(TAG, "resetting config to persistent property: " + persistConfig);
-                    SystemProperties.set("sys.usb.config", persistConfig);
+                if (!config.equals(mDefaultFunctions)) {
+                    Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions);
+                    SystemProperties.set("sys.usb.config", mDefaultFunctions);
                 }
 
-                // Read initial USB state
-                mCurrentFunctions = FileUtils.readTextFile(
-                        new File(FUNCTIONS_PATH), 0, null).trim();
-                mDefaultFunctions = mCurrentFunctions;
+                mCurrentFunctions = mDefaultFunctions;
                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
                 updateState(state);
                 mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
@@ -621,6 +618,16 @@
             pw.println("    mConnected: " + mConnected);
             pw.println("    mConfigured: " + mConfigured);
             pw.println("    mCurrentAccessory: " + mCurrentAccessory);
+            try {
+                pw.println("    Kernel state: "
+                        + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
+                pw.println("    Kernel function list: "
+                        + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
+                pw.println("    Mass storage backing file: "
+                        + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim());
+            } catch (IOException e) {
+                pw.println("IOException: " + e);
+            }
         }
     }
 
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index f33920d..e1c7305 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -39,14 +39,6 @@
     libgui \
     libusbhost
 
-ifeq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_OS),linux)
-ifeq ($(TARGET_ARCH),x86)
-LOCAL_LDLIBS += -lpthread -ldl -lrt
-endif
-endif
-endif
-
 ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
     LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
 endif
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index ba3e6e5..6a302c0 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -16,13 +16,6 @@
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
 
-# need "-lrt" on Linux simulator to pick up clock_gettime
-ifeq ($(TARGET_SIMULATOR),true)
-	ifeq ($(HOST_OS),linux)
-		LOCAL_LDLIBS += -lrt -lpthread
-	endif
-endif
-
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libhardware \
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index c618263..f67c82e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -26,13 +26,6 @@
 endif
 
 
-# need "-lrt" on Linux simulator to pick up clock_gettime
-ifeq ($(TARGET_SIMULATOR),true)
-	ifeq ($(HOST_OS),linux)
-		LOCAL_LDLIBS += -lrt -lpthread
-	endif
-endif
-
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libhardware \
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 35e29a6..f3b6c4d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -188,22 +188,37 @@
         return;
     }
 
+    /*
+     * Transformations are applied in this order:
+     * 1) buffer orientation/flip/mirror
+     * 2) state transformation (window manager)
+     * 3) layer orientation (screen orientation)
+     * (NOTE: the matrices are multiplied in reverse order)
+     */
+
+    const Transform bufferOrientation(mCurrentTransform);
+    const Transform& stateTransform(s.transform);
+    const Transform layerOrientation(mOrientation);
+
+    const Transform tr(layerOrientation * stateTransform * bufferOrientation);
+
+    // this gives us only the "orientation" component of the transform
+    const uint32_t finalTransform = tr.getOrientation();
+
     // we can only handle simple transformation
-    if (mOrientation & Transform::ROT_INVALID) {
+    if (finalTransform & Transform::ROT_INVALID) {
         hwcl->flags = HWC_SKIP_LAYER;
         return;
     }
 
-    // FIXME: shouldn't we take the state's transform into account here?
-
-    Transform tr(Transform(mOrientation) * Transform(mCurrentTransform));
-    hwcl->transform = tr.getOrientation();
+    hwcl->transform = finalTransform;
 
     if (!isOpaque()) {
         hwcl->blending = mPremultipliedAlpha ?
                 HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
     }
 
+    // scaling is already applied in mTransformedBounds
     hwcl->displayFrame.left   = mTransformedBounds.left;
     hwcl->displayFrame.top    = mTransformedBounds.top;
     hwcl->displayFrame.right  = mTransformedBounds.right;
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 0467a14..4cedcbf 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -308,6 +308,7 @@
                 scale = true;
             }
         } else {
+            // there is a skew component and/or a non 90 degrees rotation
             flags = ROT_INVALID;
         }
 
diff --git a/services/tests/servicestests/res/raw/net_dev_typical b/services/tests/servicestests/res/raw/net_dev_typical
new file mode 100644
index 0000000..290bf03
--- /dev/null
+++ b/services/tests/servicestests/res/raw/net_dev_typical
@@ -0,0 +1,8 @@
+Inter-|   Receive                                                |  Transmit
+ face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
+    lo:    8308     116    0    0    0     0          0         0     8308     116    0    0    0     0       0          0
+rmnet0: 1507570    2205    0    0    0     0          0         0   489339    2237    0    0    0     0       0          0
+  ifb0:   52454     151    0  151    0     0          0         0        0       0    0    0    0     0       0          0
+  ifb1:   52454     151    0  151    0     0          0         0        0       0    0    0    0     0       0          0
+  sit0:       0       0    0    0    0     0          0         0        0       0  148    0    0     0       0          0
+ip6tnl0:       0       0    0    0    0     0          0         0        0       0  151  151    0     0       0          0
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
index ac7cb5a..56ef995a 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
 import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
 import static com.android.server.NetworkManagementSocketTagger.tagToKernel;
 
@@ -25,9 +27,11 @@
 import android.test.suitebuilder.annotation.LargeTest;
 
 import com.android.frameworks.servicestests.R;
+import com.google.common.io.Files;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileWriter;
 import java.io.InputStream;
 import java.io.OutputStream;
 
@@ -46,14 +50,23 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mTestProc = getContext().getFilesDir();
-        mService = NetworkManagementService.createForTest(mContext, mTestProc);
+        final File canonicalFilesDir = getContext().getFilesDir().getCanonicalFile();
+        mTestProc = new File(canonicalFilesDir, "proc");
+        if (mTestProc.exists()) {
+            Files.deleteRecursively(mTestProc);
+        }
+
+        mService = NetworkManagementService.createForTest(mContext, mTestProc, true);
     }
 
     @Override
     public void tearDown() throws Exception {
         mService = null;
 
+        if (mTestProc.exists()) {
+            Files.deleteRecursively(mTestProc);
+        }
+
         super.tearDown();
     }
 
@@ -61,7 +74,7 @@
         stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
 
         final NetworkStats stats = mService.getNetworkStatsDetail();
-        assertEquals(31, stats.size);
+        assertEquals(31, stats.size());
         assertStatsEntry(stats, "wlan0", 0, 0, 14615L, 4270L);
         assertStatsEntry(stats, "wlan0", 10004, 0, 333821L, 53558L);
         assertStatsEntry(stats, "wlan0", 10004, 1947740890, 18725L, 1066L);
@@ -73,11 +86,37 @@
         stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats"));
 
         final NetworkStats stats = mService.getNetworkStatsDetail();
-        assertEquals(2, stats.size);
+        assertEquals(2, stats.size());
         assertStatsEntry(stats, "test0", 1000, 0, 1024L, 2048L);
         assertStatsEntry(stats, "test0", 1000, 0xF00D, 512L, 512L);
     }
 
+    public void testNetworkStatsSummary() throws Exception {
+        stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+
+        final NetworkStats stats = mService.getNetworkStatsSummary();
+        assertEquals(6, stats.size());
+        assertStatsEntry(stats, "lo", UID_ALL, TAG_NONE, 8308L, 8308L);
+        assertStatsEntry(stats, "rmnet0", UID_ALL, TAG_NONE, 1507570L, 489339L);
+        assertStatsEntry(stats, "ifb0", UID_ALL, TAG_NONE, 52454L, 0L);
+        assertStatsEntry(stats, "ifb1", UID_ALL, TAG_NONE, 52454L, 0L);
+        assertStatsEntry(stats, "sit0", UID_ALL, TAG_NONE, 0L, 0L);
+        assertStatsEntry(stats, "ip6tnl0", UID_ALL, TAG_NONE, 0L, 0L);
+    }
+
+    public void testNetworkStatsSummaryDown() throws Exception {
+        stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+        stageLong(1024L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_bytes"));
+        stageLong(128L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_packets"));
+        stageLong(2048L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_bytes"));
+        stageLong(256L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_packets"));
+
+        final NetworkStats stats = mService.getNetworkStatsSummary();
+        assertEquals(7, stats.size());
+        assertStatsEntry(stats, "rmnet0", UID_ALL, TAG_NONE, 1507570L, 489339L);
+        assertStatsEntry(stats, "wlan0", UID_ALL, TAG_NONE, 1024L, 2048L);
+    }
+
     public void testKernelTags() throws Exception {
         assertEquals("0", tagToKernel(0x0));
         assertEquals("214748364800", tagToKernel(0x32));
@@ -90,7 +129,6 @@
         assertEquals(2147483647, kernelToTag("0x7fffffff00000000"));
         assertEquals(0, kernelToTag("0x0000000000000000"));
         assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000"));
-
     }
 
     /**
@@ -111,11 +149,23 @@
         }
     }
 
+    private void stageLong(long value, File file) throws Exception {
+        new File(file.getParent()).mkdirs();
+        FileWriter out = null;
+        try {
+            out = new FileWriter(file);
+            out.write(Long.toString(value));
+        } finally {
+            IoUtils.closeQuietly(out);
+        }
+    }
+
     private static void assertStatsEntry(
-            NetworkStats stats, String iface, int uid, int tag, long rx, long tx) {
+            NetworkStats stats, String iface, int uid, int tag, long rxBytes, long txBytes) {
         final int i = stats.findIndex(iface, uid, tag);
-        assertEquals(rx, stats.rx[i]);
-        assertEquals(tx, stats.tx[i]);
+        final NetworkStats.Entry entry = stats.getValues(i, null);
+        assertEquals(rxBytes, entry.rxBytes);
+        assertEquals(txBytes, entry.txBytes);
     }
 
 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index b4ac987..33fd355 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -447,7 +447,7 @@
 
         // pretend that 512 bytes total have happened
         stats = new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 256L);
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L);
         expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
                 .andReturn(stats).atLeastOnce();
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index f2c28bb..ac74063 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -168,7 +168,7 @@
         expectTime(TEST_START + elapsedRealtime);
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 1L, 2048L, 2L));
         expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
 
         replay();
@@ -184,7 +184,7 @@
         expectTime(TEST_START + elapsedRealtime);
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 8192L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 4L, 8192L, 8L));
         expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
 
         replay();
@@ -219,10 +219,10 @@
         expectTime(TEST_START + elapsedRealtime);
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 8L, 2048L, 16L));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2)
-                .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 512L, 256L)
-                .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 128L));
+                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L)
+                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 128L, 1L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -264,7 +264,6 @@
     public void testStatsBucketResize() throws Exception {
         long elapsedRealtime = 0;
         NetworkStatsHistory history = null;
-        long[] total = null;
 
         assertStatsFilesExist(false);
 
@@ -284,7 +283,7 @@
         expectTime(TEST_START + elapsedRealtime);
         expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 512L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L));
         expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
 
         replay();
@@ -292,11 +291,9 @@
 
         // verify service recorded history
         history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
-        total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
-        assertEquals(512L, total[0]);
-        assertEquals(512L, total[1]);
-        assertEquals(HOUR_IN_MILLIS, history.bucketDuration);
-        assertEquals(2, history.bucketCount);
+        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
+        assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
+        assertEquals(2, history.size());
         verifyAndReset();
 
         // now change bucket duration setting and trigger another poll with
@@ -311,11 +308,9 @@
 
         // verify identical stats, but spread across 4 buckets now
         history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
-        total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
-        assertEquals(512L, total[0]);
-        assertEquals(512L, total[1]);
-        assertEquals(30 * MINUTE_IN_MILLIS, history.bucketDuration);
-        assertEquals(4, history.bucketCount);
+        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
+        assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
+        assertEquals(4, history.size());
         verifyAndReset();
 
     }
@@ -338,11 +333,11 @@
         expectTime(TEST_START + elapsedRealtime);
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 512L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3)
-                .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 512L)
-                .addEntry(TEST_IFACE, UID_RED, 0xF00D, 512L, 512L)
-                .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 0L));
+                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L)
+                .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)
+                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -373,9 +368,9 @@
         expectTime(TEST_START + elapsedRealtime);
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1024L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1024L));
+                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -412,11 +407,11 @@
         expectTime(TEST_START + elapsedRealtime);
         expectDefaultSettings();
         expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 544L));
+                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 16L, 16L)
-                .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 512L)
-                .addEntry(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 16L));
+                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L)
+                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L)
+                .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -468,8 +463,8 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 1024L)
-                .addEntry(TEST_IFACE, UID_RED, 0xF00D, 512L, 512L));
+                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L)
+                .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -497,7 +492,7 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 512L, 256L));
+                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -548,9 +543,9 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 50L, 50L)
-                .addEntry(TEST_IFACE, UID_RED, 0xF00D, 10L, 10L)
-                .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 512L));
+                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L)
+                .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L)
+                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -566,7 +561,7 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
         expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
-                .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 1024L));
+                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L));
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -574,33 +569,29 @@
         // first verify entire history present
         NetworkStats stats = mService.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
-        assertEquals(3, stats.size);
-        assertStatsEntry(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 50L);
-        assertStatsEntry(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 10L);
-        assertStatsEntry(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 1024L);
+        assertEquals(3, stats.size());
+        assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L);
+        assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L);
+        assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L);
 
         // now verify that recent history only contains one uid
         final long currentTime = TEST_START + elapsedRealtime;
         stats = mService.getSummaryForAllUid(
                 sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
-        assertEquals(1, stats.size);
-        assertStatsEntry(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 512L);
+        assertEquals(1, stats.size());
+        assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L);
 
         verifyAndReset();
     }
 
-    private void assertNetworkTotal(NetworkTemplate template, long rx, long tx) {
+    private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) {
         final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
-        final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
-        assertEquals(rx, total[0]);
-        assertEquals(tx, total[1]);
+        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes);
     }
 
-    private void assertUidTotal(NetworkTemplate template, int uid, long rx, long tx) {
+    private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) {
         final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE);
-        final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
-        assertEquals(rx, total[0]);
-        assertEquals(tx, total[1]);
+        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes);
     }
 
     private void expectSystemReady() throws Exception {
@@ -660,13 +651,24 @@
         }
     }
 
-    private static void assertStatsEntry(
-            NetworkStats stats, int i, String iface, int uid, int tag, long rx, long tx) {
-        assertEquals(iface, stats.iface[i]);
-        assertEquals(uid, stats.uid[i]);
-        assertEquals(tag, stats.tag[i]);
-        assertEquals(rx, stats.rx[i]);
-        assertEquals(tx, stats.tx[i]);
+    private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag,
+            long rxBytes, long rxPackets, long txBytes, long txPackets) {
+        final NetworkStats.Entry entry = stats.getValues(i, null);
+        assertEquals(iface, entry.iface);
+        assertEquals(uid, entry.uid);
+        assertEquals(tag, entry.tag);
+        assertEquals(rxBytes, entry.rxBytes);
+        // TODO: enable testing packet counts once stored in history
+//        assertEquals(rxPackets, entry.rxPackets);
+        assertEquals(txBytes, entry.txBytes);
+//        assertEquals(txPackets, entry.txPackets);
+    }
+
+    private static void assertValues(
+            NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) {
+        final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
     }
 
     private static NetworkState buildWifiState() {
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index 2f275c3..50c18f0 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -289,7 +289,7 @@
     public void expectGetInterfaceCounter(long rx, long tx) throws Exception {
         // TODO: provide elapsedRealtime mock to match TimeAuthority
         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
-        stats.addEntry(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, tx);
+        stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L);
 
         expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats).atLeastOnce();
     }
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 977b412..4f8b525 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -18,10 +18,12 @@
 
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.database.ContentObserver;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
@@ -334,6 +336,31 @@
         }
     };
 
+    private final DataRoamingSettingObserver mDataRoamingSettingObserver;
+
+    private class DataRoamingSettingObserver extends ContentObserver {
+        public DataRoamingSettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void register(Context context) {
+            final ContentResolver resolver = context.getContentResolver();
+            resolver.registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.DATA_ROAMING), false, this);
+        }
+
+        public void unregister(Context context) {
+            final ContentResolver resolver = context.getContentResolver();
+            resolver.unregisterContentObserver(this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            // already running on mPhone handler thread
+            handleDataOnRoamingChange();
+        }
+    }
+
     protected boolean isDataSetupCompleteOk(AsyncResult ar) {
         if (ar.exception != null) {
             if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
@@ -398,6 +425,10 @@
 
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
         mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
+
+        // watch for changes to Settings.Secure.DATA_ROAMING
+        mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone);
+        mDataRoamingSettingObserver.register(mPhone.getContext());
     }
 
     public void dispose() {
@@ -407,6 +438,7 @@
         mDataConnectionAsyncChannels.clear();
         mIsDisposed = true;
         mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
+        mDataRoamingSettingObserver.unregister(mPhone.getContext());
     }
 
     protected void broadcastMessenger() {
@@ -461,32 +493,38 @@
         return result;
     }
 
-    //The data roaming setting is now located in the shared preferences.
-    //  See if the requested preference value is the same as that stored in
-    //  the shared values.  If it is not, then update it.
+    /**
+     * Modify {@link Settings.Secure#DATA_ROAMING} value.
+     */
     public void setDataOnRoamingEnabled(boolean enabled) {
         if (getDataOnRoamingEnabled() != enabled) {
-            Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
-                Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
-            if (mPhone.getServiceState().getRoaming()) {
-                if (enabled) {
-                    resetAllRetryCounts();
-                }
-                sendMessage(obtainMessage(EVENT_ROAMING_ON));
-            }
+            final ContentResolver resolver = mPhone.getContext().getContentResolver();
+            Settings.Secure.putInt(resolver, Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
+            // will trigger handleDataOnRoamingChange() through observer
         }
     }
 
-    // Retrieve the data roaming setting from the shared preferences.
+    /**
+     * Return current {@link Settings.Secure#DATA_ROAMING} value.
+     */
     public boolean getDataOnRoamingEnabled() {
         try {
-            return Settings.Secure.getInt(
-                    mPhone.getContext().getContentResolver(), Settings.Secure.DATA_ROAMING) > 0;
+            final ContentResolver resolver = mPhone.getContext().getContentResolver();
+            return Settings.Secure.getInt(resolver, Settings.Secure.DATA_ROAMING) != 0;
         } catch (SettingNotFoundException snfe) {
             return false;
         }
     }
 
+    private void handleDataOnRoamingChange() {
+        if (mPhone.getServiceState().getRoaming()) {
+            if (getDataOnRoamingEnabled()) {
+                resetAllRetryCounts();
+            }
+            sendMessage(obtainMessage(EVENT_ROAMING_ON));
+        }
+    }
+
     // abstract methods
     protected abstract String getActionIntentReconnectAlarm();
     protected abstract void startNetStatPoll();
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 4309309..60cf9b7 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -166,4 +166,11 @@
      * the value of config_sms_capable
      */
     static final String PROPERTY_SMS_SEND = "telephony.sms.send";
+
+    /**
+     * Set to true to indicate a test CSIM card is used in the device.
+     * This property is for testing purpose only. This should not be defined
+     * in commercial configuration.
+     */
+    static final String PROPERTY_TEST_CSIM = "persist.radio.test-csim";
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 459cf87..0d551aa 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -39,7 +39,6 @@
     CDMALTEPhone mCdmaLtePhone;
 
     private ServiceState  mLteSS;  // The last LTE state from Voice Registration
-    private String mCurrentSpn = null;
 
     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
         super(phone);
@@ -345,6 +344,18 @@
                 ss.setOperatorAlphaLong(eriText);
             }
 
+            if (cm.getSimState().isSIMReady()) {
+                // SIM is found on the device. If ERI roaming is OFF, use operator name
+                // from CSIM record.
+                boolean showSpn =
+                    ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
+                int iconIndex = ss.getCdmaEriIconIndex();
+
+                if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)) {
+                    ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName());
+                }
+            }
+
             String operatorNumeric;
 
             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
@@ -468,43 +479,6 @@
     }
 
     @Override
-    protected void updateSpnDisplay() {
-        // mOperatorAlphaLong contains the ERI text
-        String plmn = ss.getOperatorAlphaLong();
-
-        boolean showSpn = false;
-        String spn = null;
-        if (cm.getSimState().isSIMReady()) {
-            // SIM is found on the device. Read the operator name from the card.
-            showSpn = ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
-            spn = phone.mIccRecords.getServiceProviderName();
-
-            // double check we are not printing identicall test
-            if (TextUtils.equals(plmn, spn)) showSpn = false;
-        }
-
-        if (!TextUtils.equals(plmn, mCurPlmn) ||
-            !TextUtils.equals(spn, mCurrentSpn)) {
-            boolean showPlmn = plmn != null;
-            if (DBG) {
-                log(String.format("updateSpnDisplay: changed sending intent" +
-                                  " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'",
-                                  showPlmn, plmn, showSpn, spn));
-            }
-            Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
-            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
-            intent.putExtra(Intents.EXTRA_SPN, spn);
-            intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
-            intent.putExtra(Intents.EXTRA_PLMN, plmn);
-            phone.getContext().sendStickyBroadcast(intent);
-        }
-
-        mCurPlmn = plmn;
-        mCurrentSpn = spn;
-    }
-
-    @Override
     protected void log(String s) {
         Log.d(LOG_TAG, "[CdmaLteSST] " + s);
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
index 10515f7..fc6abad 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -16,6 +16,7 @@
 package com.android.internal.telephony.cdma;
 
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;
 import com.android.internal.telephony.GsmAlphabet;
 import com.android.internal.telephony.IccCardApplication.AppType;
 import com.android.internal.telephony.IccFileHandler;
@@ -447,6 +448,12 @@
         // to determine if the SIM is provisioned.  Otherwise,
         // consider the SIM is provisioned. (for case of ordinal
         // USIM only UICC.)
+        // If PROPERTY_TEST_CSIM is defined, bypess provision check
+        // and consider the SIM is provisioned.
+        if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
+            return true;
+        }
+
         if (phone.mIccCard.isApplicationOnIcc(AppType.APPTYPE_CSIM) &&
             ((mMdn == null) || (mMin == null))) {
             return false;
diff --git a/tests/BiDiTests/res/layout/textview_drawables_ltr.xml b/tests/BiDiTests/res/layout/textview_drawables_ltr.xml
new file mode 100644
index 0000000..88b13b7
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_drawables_ltr.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_drawables_ltr"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="ltr">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent">
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/end"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableRight="@drawable/start"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/end"
+                  android:drawableRight="@drawable/start"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableRight="@drawable/end"
+                  android:drawableStart="@drawable/start"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:id="@+id/textview_error"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawablePadding="3dip"
+                />
+
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_drawables_rtl.xml b/tests/BiDiTests/res/layout/textview_drawables_rtl.xml
new file mode 100644
index 0000000..7f47d5d
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_drawables_rtl.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_drawables_rtl"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="rtl">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent">
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/end"
+                  android:drawableRight="@drawable/start"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableRight="@drawable/end"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/start"
+                  android:drawableRight="@drawable/end"
+                  android:drawableStart="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableLeft="@drawable/end"
+                  android:drawableStart="@drawable/start"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawableRight="@drawable/start"
+                  android:drawableEnd="@drawable/end"
+                  android:drawablePadding="3dip"
+                />
+
+        <TextView android:id="@+id/textview_error"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+                  android:drawablePadding="3dip"
+                />
+
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index c033879..7002c41 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -134,6 +134,9 @@
         addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
         addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
 
+        addItem(result, "TextView Drawables LTR", BiDiTestTextViewDrawablesLtr.class, R.id.textview_drawables_ltr);
+        addItem(result, "TextView Drawables RTL", BiDiTestTextViewDrawablesRtl.class, R.id.textview_drawables_rtl);
+
         return result;
     }
 
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java
new file mode 100644
index 0000000..a65d92d
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class BiDiTestTextViewDrawablesLtr extends Fragment {
+
+    private View currentView;
+    private TextView textViewError;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        currentView = inflater.inflate(R.layout.textview_drawables_ltr, container, false);
+        return currentView;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        textViewError = (TextView) currentView.findViewById(R.id.textview_error);
+        textViewError.setError("Error!!");
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java
new file mode 100644
index 0000000..7b7e812
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class BiDiTestTextViewDrawablesRtl extends Fragment {
+
+    private View currentView;
+    private TextView textViewError;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        currentView = inflater.inflate(R.layout.textview_drawables_rtl, container, false);
+        return currentView;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        textViewError = (TextView) currentView.findViewById(R.id.textview_error);
+        textViewError.setError("Error!!");
+    }
+}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index cb8084d..32a6a65 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -382,6 +382,15 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity
+                android:name="MoreNinePatchesActivity"
+                android:label="_9patch2">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
         
         <activity
                 android:name="QuickRejectActivity"
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png
new file mode 100644
index 0000000..089704e
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png
new file mode 100644
index 0000000..385dbc4
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png
new file mode 100644
index 0000000..f1510b24
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png
new file mode 100644
index 0000000..4208c6f
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png
new file mode 100644
index 0000000..b25fb2f
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png
new file mode 100644
index 0000000..25129c6
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png
new file mode 100644
index 0000000..1505e0e
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml b/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml
new file mode 100644
index 0000000..9eb54b7
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@android:id/background"
+          android:drawable="@drawable/progress_vertical_bg_holo_dark" />
+
+    <item android:id="@android:id/secondaryProgress">
+        <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+               android:drawable="@drawable/progress_vertical_secondary_holo_dark" />
+    </item>
+
+    <item android:id="@android:id/progress">
+        <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+               android:drawable="@drawable/progress_vertical_primary_holo_dark" />
+    </item>
+
+</layer-list>
diff --git a/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml b/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml
new file mode 100644
index 0000000..0cc56bf
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background"
+            android:drawable="@drawable/scrubber_vertical_track_holo_dark" />
+    <item android:id="@android:id/secondaryProgress">
+        <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+                android:drawable="@drawable/scrubber_vertical_secondary_holo" />
+    </item>
+    <item android:id="@android:id/progress">
+        <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+                android:drawable="@drawable/scrubber_vertical_primary_holo" />
+    </item>
+</layer-list>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java
new file mode 100644
index 0000000..0c42387
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MoreNinePatchesActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        FrameLayout layout = new FrameLayout(this);
+        PatchView b = new PatchView (this);
+        b.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
+                FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER));
+        layout.addView(b);
+        layout.setBackgroundColor(0xffffffff);
+        
+        setContentView(layout);
+    }
+
+    private class PatchView extends View {
+        private final Drawable mDrawable1;
+        private final Drawable mDrawable2;
+        private final Drawable mDrawable3;
+
+        private PatchView(Context context) {
+            super(context);
+            Resources res = context.getResources();
+            mDrawable1 = res.getDrawable(R.drawable.progress_vertical_holo_dark);
+            mDrawable2 = res.getDrawable(R.drawable.scrubber_progress_vertical_holo_dark);
+            mDrawable3 = res.getDrawable(R.drawable.scrubber_vertical_primary_holo);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+
+            canvas.translate(100, 100);
+            mDrawable1.setBounds(0, 0, 33, 120);
+            mDrawable1.setLevel(5000);
+            mDrawable1.draw(canvas);
+
+            canvas.translate(20, 0);
+            mDrawable2.setBounds(0, 0, 33, 120);
+            mDrawable2.setLevel(5000);
+            mDrawable2.draw(canvas);
+
+            canvas.translate(20, 0);
+            mDrawable3.setBounds(0, 0, 33, 120);
+            mDrawable3.draw(canvas);            
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/FBOTest/Android.mk b/tests/RenderScriptTests/FBOTest/Android.mk
index 55525c4..1df7b26 100644
--- a/tests/RenderScriptTests/FBOTest/Android.mk
+++ b/tests/RenderScriptTests/FBOTest/Android.mk
@@ -14,8 +14,6 @@
 # limitations under the License.
 #
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -26,5 +24,3 @@
 LOCAL_PACKAGE_NAME := FBOTest
 
 include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/ImageProcessing/Android.mk b/tests/RenderScriptTests/ImageProcessing/Android.mk
index 7fa30d0..507cc92 100644
--- a/tests/RenderScriptTests/ImageProcessing/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing/Android.mk
@@ -14,8 +14,6 @@
 # limitations under the License.
 #
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -28,5 +26,3 @@
 LOCAL_PACKAGE_NAME := ImageProcessing
 
 include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/ModelViewer/Android.mk b/tests/RenderScriptTests/ModelViewer/Android.mk
index efe77d7..1d9bacf 100644
--- a/tests/RenderScriptTests/ModelViewer/Android.mk
+++ b/tests/RenderScriptTests/ModelViewer/Android.mk
@@ -14,8 +14,6 @@
 # limitations under the License.
 #
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -27,5 +25,3 @@
 LOCAL_PACKAGE_NAME := ModelViewer
 
 include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/PerfTest/Android.mk b/tests/RenderScriptTests/PerfTest/Android.mk
index 757b3b1..0d1e7d2 100644
--- a/tests/RenderScriptTests/PerfTest/Android.mk
+++ b/tests/RenderScriptTests/PerfTest/Android.mk
@@ -14,8 +14,6 @@
 # limitations under the License.
 #
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -29,5 +27,3 @@
 LOCAL_PACKAGE_NAME := PerfTest
 
 include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/tests/Android.mk b/tests/RenderScriptTests/tests/Android.mk
index 6c992d5..880b80f 100644
--- a/tests/RenderScriptTests/tests/Android.mk
+++ b/tests/RenderScriptTests/tests/Android.mk
@@ -14,8 +14,6 @@
 # limitations under the License.
 #
 
-ifneq ($(TARGET_SIMULATOR),true)
-
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -26,5 +24,3 @@
 LOCAL_PACKAGE_NAME := RSTest
 
 include $(BUILD_PACKAGE)
-
-endif
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..ac5a97b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..a90dc9b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..cb3c433
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
index 4bcd2be..5ab09f0 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
index cfeba3e..62ca427 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
index 1d97e05..ff698fb 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4cb305d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..31d35c8
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..f0cc341d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
new file mode 100644
index 0000000..83f9cc2
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.layoutlib.bridge.android.BridgeWindowManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.os.RemoteException;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link Display}
+ *
+ * Through the layoutlib_create tool, the original  methods of Display have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class Display_Delegate {
+
+    // ---- Overridden methods ----
+
+    @LayoutlibDelegate
+    public static IWindowManager getWindowManager() {
+        return RenderAction.getCurrentContext().getIWindowManager();
+    }
+
+    // ---- Native methods ----
+
+    @LayoutlibDelegate
+    /*package*/ static int getDisplayCount() {
+        return 1;
+    }
+
+    @LayoutlibDelegate
+    /** @hide Returns the actual screen size, not including any decor. */
+    /*package*/ static int getRealWidth(Display theDisplay) {
+        // always dynamically query for the current window manager
+        return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels;
+    }
+
+    @LayoutlibDelegate
+    /** @hide Returns the actual screen size, not including any decor. */
+    /*package*/ static int getRealHeight(Display theDisplay) {
+        // always dynamically query for the current window manager
+        return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels;
+    }
+
+    @LayoutlibDelegate
+    /** @hide special for when we are faking the screen size. */
+    /*package*/ static int getRawWidth(Display theDisplay) {
+        // same as real since we're not faking compatibility mode.
+        return getRealWidth(theDisplay);
+    }
+
+    @LayoutlibDelegate
+    /** @hide special for when we are faking the screen size. */
+    /*package*/ static int getRawHeight(Display theDisplay) {
+        // same as real since we're not faking compatibility mode.
+        return getRealHeight(theDisplay);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static int getOrientation(Display theDisplay) {
+        try {
+            // always dynamically query for the current window manager
+            return getWindowManager().getRotation();
+        } catch (RemoteException e) {
+            // this will never been thrown since this is not a true RPC.
+        }
+
+        return Surface.ROTATION_0;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nativeClassInit() {
+        // not needed for now.
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void init(Display theDisplay, int display) {
+        // always dynamically query for the current window manager
+        BridgeWindowManager wm = RenderAction.getCurrentContext().getIWindowManager();
+        theDisplay.mDensity = wm.getMetrics().density;
+        theDisplay.mDpiX = wm.getMetrics().xdpi;
+        theDisplay.mDpiY = wm.getMetrics().ydpi;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
index 251c053..1fd7836 100644
--- a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
+++ b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
@@ -16,8 +16,11 @@
 
 package android.view.accessibility;
 
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.Context;
 import android.content.pm.ServiceInfo;
+import android.view.IWindow;
+import android.view.View;
 
 import java.util.Collections;
 import java.util.List;
@@ -38,6 +41,19 @@
     private static AccessibilityManager sInstance = new AccessibilityManager();
 
     /**
+     * Listener for the accessibility state.
+     */
+    public interface AccessibilityStateChangeListener {
+
+        /**
+         * Called back on change in the accessibility state.
+         *
+         * @param enabled Whether accessibility is enabled.
+         */
+        public void onAccessibilityStateChanged(boolean enabled);
+    }
+
+    /**
      * Get an AccessibilityManager instance (create one if necessary).
      *
      * @hide
@@ -92,4 +108,30 @@
         List<ServiceInfo> services = null;
         return Collections.unmodifiableList(services);
     }
+
+    public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
+        // normal implementation does this in some case, so let's do the same
+        // (unmodifiableList wrapped around null).
+        List<AccessibilityServiceInfo> services = null;
+        return Collections.unmodifiableList(services);
+    }
+
+    public boolean addAccessibilityStateChangeListener(
+            AccessibilityStateChangeListener listener) {
+        return true;
+    }
+
+    public boolean removeAccessibilityStateChangeListener(
+            AccessibilityStateChangeListener listener) {
+        return true;
+    }
+
+    public int addAccessibilityInteractionConnection(IWindow windowToken,
+            IAccessibilityInteractionConnection connection) {
+        return View.NO_ID;
+    }
+
+    public void removeAccessibilityInteractionConnection(IWindow windowToken) {
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
new file mode 100644
index 0000000..ec7a67e
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import com.android.layoutlib.bridge.android.BridgeIInputMethodManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.os.Looper;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link InputMethodManager}
+ *
+ * Through the layoutlib_create tool, the original  methods of InputMethodManager have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class InputMethodManager_Delegate {
+
+    // ---- Overridden methods ----
+
+    @LayoutlibDelegate
+    /*package*/ static InputMethodManager getInstance(Looper mainLooper) {
+        synchronized (InputMethodManager.mInstanceSync) {
+            if (InputMethodManager.mInstance != null) {
+                return InputMethodManager.mInstance;
+            }
+
+            InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
+                    mainLooper);
+        }
+        return InputMethodManager.mInstance;
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 47fa68e..69e0de9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -64,6 +64,7 @@
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
+import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -91,7 +92,11 @@
     private final Object mProjectKey;
     private final DisplayMetrics mMetrics;
     private final RenderResources mRenderResources;
+    private final Configuration mConfig;
     private final ApplicationInfo mApplicationInfo;
+    private final IProjectCallback mProjectCallback;
+
+    private final BridgeWindowManager mIWindowManager;
 
     private final Map<Object, Map<String, String>> mDefaultPropMaps =
         new IdentityHashMap<Object, Map<String,String>>();
@@ -105,7 +110,6 @@
     private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
     private BridgeInflater mBridgeInflater;
 
-    private final IProjectCallback mProjectCallback;
     private BridgeContentResolver mContentResolver;
 
     private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
@@ -113,28 +117,25 @@
     /**
      * @param projectKey An Object identifying the project. This is used for the cache mechanism.
      * @param metrics the {@link DisplayMetrics}.
-     * @param themeName The name of the theme to use.
-     * @param projectResources the resources of the project. The map contains (String, map) pairs
-     * where the string is the type of the resource reference used in the layout file, and the
-     * map contains (String, {@link }) pairs where the key is the resource name,
-     * and the value is the resource value.
-     * @param frameworkResources the framework resources. The map contains (String, map) pairs
-     * where the string is the type of the resource reference used in the layout file, and the map
-     * contains (String, {@link ResourceValue}) pairs where the key is the resource name, and the
-     * value is the resource value.
-     * @param styleInheritanceMap
+     * @param renderResources the configured resources (both framework and projects) for this
+     * render.
      * @param projectCallback
+     * @param config the Configuration object for this render.
      * @param targetSdkVersion the targetSdkVersion of the application.
      */
     public BridgeContext(Object projectKey, DisplayMetrics metrics,
             RenderResources renderResources,
             IProjectCallback projectCallback,
+            Configuration config,
             int targetSdkVersion) {
         mProjectKey = projectKey;
         mMetrics = metrics;
         mProjectCallback = projectCallback;
 
         mRenderResources = renderResources;
+        mConfig = config;
+
+        mIWindowManager = new BridgeWindowManager(mConfig, metrics, Surface.ROTATION_0);
 
         mFragments.mCurState = Fragment.CREATED;
         mFragments.mActivity = this;
@@ -151,13 +152,12 @@
      */
     public void initResources() {
         AssetManager assetManager = AssetManager.getSystem();
-        Configuration config = new Configuration();
 
         mSystemResources = BridgeResources.initSystem(
                 this,
                 assetManager,
                 mMetrics,
-                config,
+                mConfig,
                 mProjectCallback);
         mTheme = mSystemResources.newTheme();
     }
@@ -197,6 +197,10 @@
         return mRenderResources;
     }
 
+    public BridgeWindowManager getIWindowManager() {
+        return mIWindowManager;
+    }
+
     public Map<String, String> getDefaultPropMap(Object key) {
         return mDefaultPropMaps.get(key);
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
new file mode 100644
index 0000000..1394c32
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.android;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+import com.android.internal.view.IInputMethodManager;
+import com.android.internal.view.InputBindResult;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.text.style.SuggestionSpan;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.List;
+
+/**
+ * Basic implementation of IInputMethodManager that does nothing.
+ *
+ */
+public class BridgeIInputMethodManager implements IInputMethodManager {
+
+    public void addClient(IInputMethodClient arg0, IInputContext arg1, int arg2, int arg3)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void finishInput(IInputMethodClient arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public InputMethodSubtype getCurrentInputMethodSubtype() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<InputMethodInfo> getEnabledInputMethodList() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo arg0,
+            boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List<InputMethodInfo> getInputMethodList() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public InputMethodSubtype getLastInputMethodSubtype() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public List getShortcutInputMethodsAndSubtypes() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void hideMySoftInput(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean hideSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean notifySuggestionPicked(SuggestionSpan arg0, String arg1, int arg2)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void registerSuggestionSpansForNotification(SuggestionSpan[] arg0)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void removeClient(IInputMethodClient arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void setImeWindowStatus(IBinder arg0, int arg1, int arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setInputMethod(IBinder arg0, String arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setInputMethodAndSubtype(IBinder arg0, String arg1, InputMethodSubtype arg2)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean setInputMethodEnabled(String arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void showInputMethodAndSubtypeEnablerFromClient(IInputMethodClient arg0, String arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void showInputMethodPickerFromClient(IInputMethodClient arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void showMySoftInput(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean showSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public InputBindResult startInput(IInputMethodClient arg0, IInputContext arg1, EditorInfo arg2,
+            boolean arg3, boolean arg4) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void windowGainedFocus(IInputMethodClient arg0, IBinder arg1, boolean arg2,
+            boolean arg3, int arg4, boolean arg5, int arg6) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public IBinder asBinder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
new file mode 100644
index 0000000..13cd9ec
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.android;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Display_Delegate;
+import android.view.IApplicationToken;
+import android.view.IOnKeyguardExitResult;
+import android.view.IRotationWatcher;
+import android.view.IWindowManager;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.util.List;
+
+/**
+ * Basic implementation of {@link IWindowManager} so that {@link Display} (and
+ * {@link Display_Delegate}) can return a valid instance.
+ */
+public class BridgeWindowManager implements IWindowManager {
+
+    private final Configuration mConfig;
+    private final DisplayMetrics mMetrics;
+    private final int mRotation;
+
+    public BridgeWindowManager(Configuration config, DisplayMetrics metrics, int rotation) {
+        mConfig = config;
+        mMetrics = metrics;
+        mRotation = rotation;
+    }
+
+    // custom API.
+
+    public DisplayMetrics getMetrics() {
+        return mMetrics;
+    }
+
+    // ---- implementation of IWindowManager that we care about ----
+
+    public int getRotation() throws RemoteException {
+        return mRotation;
+    }
+
+    public int getMaximumSizeDimension() throws RemoteException {
+        return 0;
+    }
+
+    public void getDisplaySize(Point arg0) throws RemoteException {
+    }
+
+    // ---- unused implementation of IWindowManager ----
+
+    public boolean canStatusBarHide() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void addWindowToken(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void clearForcedDisplaySize() throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void closeSystemDialogs(String arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void executeAppTransition() throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void freezeRotation() throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public float getAnimationScale(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public float[] getAnimationScales() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int getAppOrientation(IApplicationToken arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getDPadKeycodeState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getDPadScancodeState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+
+    public InputDevice getInputDevice(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int[] getInputDeviceIds() throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int getKeycodeState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getKeycodeStateForDevice(int arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+
+    public int getPendingAppTransition() throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+
+    public int getScancodeState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getScancodeStateForDevice(int arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getSwitchState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getSwitchStateForDevice(int arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getTrackballKeycodeState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int getTrackballScancodeState(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public boolean hasKeys(int[] arg0, boolean[] arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean inKeyguardRestrictedInputMode() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean injectInputEventNoWait(InputEvent arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean injectKeyEvent(KeyEvent arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean injectPointerEvent(MotionEvent arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean injectTrackballEvent(MotionEvent arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean isKeyguardLocked() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean isKeyguardSecure() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean isViewServerRunning() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public InputChannel monitorInput(String arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void overridePendingAppTransition(String arg0, int arg1, int arg2)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void reenableKeyguard(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void removeAppToken(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void removeWindowToken(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void resumeKeyDispatching(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public Bitmap screenshotApplications(IBinder arg0, int arg1, int arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void setAnimationScale(int arg0, float arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAnimationScales(float[] arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
+            CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAppVisibility(IBinder arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAppWillBeHidden(IBinder arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setEventDispatching(boolean arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setForcedDisplaySize(int arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setInTouchMode(boolean arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setNewConfiguration(Configuration arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setPointerSpeed(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setRotation(int arg0, boolean arg1, int arg2) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void showStrictModeViolation(boolean arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void startAppFreezingScreen(IBinder arg0, int arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean startViewServer(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void statusBarVisibilityChanged(int arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void stopAppFreezingScreen(IBinder arg0, boolean arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public boolean stopViewServer() throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void thawRotation() throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public int watchRotation(IRotationWatcher arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public IBinder asBinder() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 6194f5d..d40222f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -27,10 +27,16 @@
 import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.resources.Density;
 import com.android.resources.ResourceType;
+import com.android.resources.ScreenSize;
 
+import android.content.res.Configuration;
 import android.os.HandlerThread_Delegate;
+import android.os.Looper;
 import android.util.DisplayMetrics;
+import android.view.ViewConfiguration;
+import android.view.inputmethod.InputMethodManager;
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
@@ -94,24 +100,29 @@
         // setup the display Metrics.
         DisplayMetrics metrics = new DisplayMetrics();
         metrics.densityDpi = mParams.getDensity().getDpiValue();
-        metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
-        metrics.scaledDensity = metrics.density;
-        metrics.widthPixels = mParams.getScreenWidth();
-        metrics.heightPixels = mParams.getScreenHeight();
-        metrics.xdpi = mParams.getXdpi();
-        metrics.ydpi = mParams.getYdpi();
+
+        metrics.density = metrics.noncompatDensity =
+                metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
+
+        metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;
+
+        metrics.widthPixels = metrics.noncompatWidthPixels = mParams.getScreenWidth();
+        metrics.heightPixels = metrics.noncompatHeightPixels = mParams.getScreenHeight();
+        metrics.xdpi = metrics.noncompatXdpi = mParams.getXdpi();
+        metrics.ydpi = metrics.noncompatYdpi = mParams.getYdpi();
 
         RenderResources resources = mParams.getResources();
 
         // build the context
         mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
-                mParams.getProjectCallback(), mParams.getTargetSdkVersion());
+                mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion());
 
         setUp();
 
         return SUCCESS.createResult();
     }
 
+
     /**
      * Prepares the scene for action.
      * <p>
@@ -215,6 +226,9 @@
         mContext.initResources();
         sCurrentContext = mContext;
 
+        // create an InputMethodManager
+        InputMethodManager.getInstance(Looper.myLooper());
+
         LayoutLog currentLog = mParams.getLog();
         Bridge.setLog(currentLog);
         mContext.getRenderResources().setFrameworkResourceIdProvider(this);
@@ -233,6 +247,12 @@
         // quit HandlerThread created during this session.
         HandlerThread_Delegate.cleanUp(sCurrentContext);
 
+        // clear the stored ViewConfiguration since the map is per density and not per context.
+        ViewConfiguration.sConfigurations.clear();
+
+        // remove the InputMethodManager
+        InputMethodManager.mInstance = null;
+
         sCurrentContext = null;
 
         Bridge.setLog(null);
@@ -281,6 +301,50 @@
         }
     }
 
+    private Configuration getConfiguration() {
+        Configuration config = new Configuration();
+
+        ScreenSize screenSize = mParams.getConfigScreenSize();
+        if (screenSize != null) {
+            switch (screenSize) {
+                case SMALL:
+                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL;
+                    break;
+                case NORMAL:
+                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL;
+                    break;
+                case LARGE:
+                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE;
+                    break;
+                case XLARGE:
+                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+                    break;
+            }
+        }
+
+        Density density = mParams.getDensity();
+        if (density == null) {
+            density = Density.MEDIUM;
+        }
+
+        config.screenWidthDp = mParams.getScreenWidth() / density.getDpiValue();
+        config.screenHeightDp = mParams.getScreenHeight() / density.getDpiValue();
+        if (config.screenHeightDp < config.screenWidthDp) {
+            config.smallestScreenWidthDp = config.screenHeightDp;
+        } else {
+            config.smallestScreenWidthDp = config.screenWidthDp;
+        }
+
+        // never run in compat mode:
+        config.compatScreenWidthDp = config.screenWidthDp;
+        config.compatScreenHeightDp = config.screenHeightDp;
+
+        // TODO: fill in more config info.
+
+        return config;
+    }
+
+
     // --- FrameworkResourceIdProvider methods
 
     @Override
diff --git a/tools/layoutlib/bridge/tests/.classpath b/tools/layoutlib/bridge/tests/.classpath
index 9cc2433d..027bc67 100644
--- a/tools/layoutlib/bridge/tests/.classpath
+++ b/tools/layoutlib/bridge/tests/.classpath
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="res"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/layoutlib_bridge"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 233f72ec..df7e04f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -103,9 +103,11 @@
         "android.os.Handler#sendMessageAtTime",
         "android.os.HandlerThread#run",
         "android.os.Build#getString",
+        "android.view.Display#getWindowManager",
         "android.view.LayoutInflater#rInflate",
         "android.view.LayoutInflater#parseInclude",
         "android.view.View#isInEditMode",
+        "android.view.inputmethod.InputMethodManager#getInstance",
         "com.android.internal.util.XmlUtils#convertValueToInt",
         // TODO: comment out once DelegateClass is working
     };
@@ -154,6 +156,7 @@
         "android.graphics.Xfermode",
         "android.os.SystemClock",
         "android.util.FloatMath",
+        "android.view.Display",
         "libcore.icu.ICU",
     };