Merge "Fix blip after notifications are swiped"
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 882dd6b..8d17325 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -42,11 +42,12 @@
      * @param interactionId The id of the interaction for matching with the callback result.
      * @param callback Callback which to receive the result.
      * @param threadId The id of the calling thread.
+     * @param prefetchFlags flags to guide prefetching.
      * @return The current window scale, where zero means a failure.
      */
     float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
         long accessibilityNodeId, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, long threadId);
+        IAccessibilityInteractionConnectionCallback callback, long threadId, int prefetchFlags);
 
     /**
      * Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by View text.
diff --git a/core/java/android/accessibilityservice/UiTestAutomationBridge.java b/core/java/android/accessibilityservice/UiTestAutomationBridge.java
index 334981a..9b3da53 100644
--- a/core/java/android/accessibilityservice/UiTestAutomationBridge.java
+++ b/core/java/android/accessibilityservice/UiTestAutomationBridge.java
@@ -57,6 +57,11 @@
 
     public static final int UNDEFINED = -1;
 
+    private static final int FIND_ACCESSIBILITY_NODE_INFO_PREFETCH_FLAGS =
+        AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS
+        | AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
+        | AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS;
+
     private final Object mLock = new Object();
 
     private volatile int mConnectionId = AccessibilityInteractionClient.NO_ID;
@@ -351,13 +356,15 @@
         ensureValidConnection(connectionId);
         return AccessibilityInteractionClient.getInstance()
                 .findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
-                        accessibilityWindowId, accessibilityNodeId);
+                        accessibilityWindowId, accessibilityNodeId,
+                        FIND_ACCESSIBILITY_NODE_INFO_PREFETCH_FLAGS);
     }
 
     /**
      * Finds an {@link AccessibilityNodeInfo} by View id in the active
      * window. The search is performed from the root node.
      *
+     * @param viewId The id of a View.
      * @return The current window scale, where zero means a failure.
      */
     public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) {
@@ -373,6 +380,7 @@
      *     {@link  #ACTIVE_WINDOW_ID} to query the currently active window.
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use {@link  #ROOT_NODE_ID} to start from the root.
+     * @param viewId The id of a View.
      * @return The current window scale, where zero means a failure.
      */
     public AccessibilityNodeInfo findAccessibilityNodeInfoByViewId(int accessibilityWindowId,
@@ -460,7 +468,7 @@
         ensureValidConnection(connectionId);
         return AccessibilityInteractionClient.getInstance()
                 .findAccessibilityNodeInfoByAccessibilityId(connectionId, ACTIVE_WINDOW_ID,
-                        ROOT_NODE_ID);
+                        ROOT_NODE_ID, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
     }
 
     private void ensureValidConnection(int connectionId) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 7054851..ec95863 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -910,8 +910,6 @@
             if (canDraw()) {
                 if (!hasDirtyRegions()) {
                     dirty = null;
-                } else if (dirty != null) {
-                    dirty.intersect(0, 0, mWidth, mHeight);
                 }
                 attachInfo.mIgnoreDirtyState = true;
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 28737fc..31d874f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -54,12 +54,12 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
-import android.util.LongSparseArray;
 import android.util.Pool;
 import android.util.Poolable;
 import android.util.PoolableManager;
 import android.util.Pools;
 import android.util.Slog;
+import android.util.SparseLongArray;
 import android.util.TypedValue;
 import android.view.View.AttachInfo;
 import android.view.View.MeasureSpec;
@@ -87,7 +87,9 @@
 import java.io.OutputStream;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
@@ -309,7 +311,7 @@
 
     SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
 
-    AccessibilityPrefetchStrategy mAccessibilityPrefetchStrategy;
+    AccessibilityNodePrefetcher mAccessibilityNodePrefetcher;
 
     private final int mDensity;
 
@@ -379,8 +381,6 @@
         mAccessibilityManager = AccessibilityManager.getInstance(context);
         mAccessibilityInteractionConnectionManager =
             new AccessibilityInteractionConnectionManager();
-        mAccessibilityManager.addAccessibilityStateChangeListener(
-                mAccessibilityInteractionConnectionManager);
         mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, mHandler, this);
         mViewConfiguration = ViewConfiguration.get(context);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
@@ -771,19 +771,29 @@
         return mLayoutRequested;
     }
 
+    void invalidate() {
+        mDirty.set(0, 0, mWidth, mHeight);
+        scheduleTraversals();
+    }
+
     public void invalidateChild(View child, Rect dirty) {
+        invalidateChildInParent(null, dirty);
+    }
+
+    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
         checkThread();
         if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
+
         if (dirty == null) {
-            // Fast invalidation for GL-enabled applications; GL must redraw everything
             invalidate();
-            return;
+            return null;
         }
+
         if (mCurScrollY != 0 || mTranslator != null) {
             mTempRect.set(dirty);
             dirty = mTempRect;
             if (mCurScrollY != 0) {
-               dirty.offset(0, -mCurScrollY);
+                dirty.offset(0, -mCurScrollY);
             }
             if (mTranslator != null) {
                 mTranslator.translateRectInAppWindowToScreen(dirty);
@@ -792,19 +802,24 @@
                 dirty.inset(-1, -1);
             }
         }
-        if (!mDirty.isEmpty() && !mDirty.contains(dirty)) {
+
+        final Rect localDirty = mDirty;
+        if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {
             mAttachInfo.mSetIgnoreDirtyState = true;
             mAttachInfo.mIgnoreDirtyState = true;
         }
-        mDirty.union(dirty);
+
+        // Add the new dirty rect to the current one
+        localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);
+        // Intersect with the bounds of the window to skip
+        // updates that lie outside of the visible region
+        localDirty.intersect(0, 0, mWidth, mHeight);
+
         if (!mWillDrawSoon) {
             scheduleTraversals();
         }
-    }
-    
-    void invalidate() {
-        mDirty.set(0, 0, mWidth, mHeight);
-        scheduleTraversals();
+
+        return null;
     }
 
     void setStopped(boolean stopped) {
@@ -815,13 +830,8 @@
             }
         }
     }
-    
-    public ViewParent getParent() {
-        return null;
-    }
 
-    public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
-        invalidateChild(null, dirty);
+    public ViewParent getParent() {
         return null;
     }
 
@@ -3554,15 +3564,15 @@
         return mAccessibilityInteractionController;
     }
 
-    public AccessibilityPrefetchStrategy getAccessibilityPrefetchStrategy() {
+    public AccessibilityNodePrefetcher getAccessibilityNodePrefetcher() {
         if (mView == null) {
-            throw new IllegalStateException("getAccessibilityPrefetchStrategy"
+            throw new IllegalStateException("getAccessibilityNodePrefetcher"
                     + " called when there is no mView");
         }
-        if (mAccessibilityPrefetchStrategy == null) {
-            mAccessibilityPrefetchStrategy = new AccessibilityPrefetchStrategy();
+        if (mAccessibilityNodePrefetcher == null) {
+            mAccessibilityNodePrefetcher = new AccessibilityNodePrefetcher();
         }
-        return mAccessibilityPrefetchStrategy;
+        return mAccessibilityNodePrefetcher;
     }
 
     private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
@@ -4108,7 +4118,6 @@
         if (mView == null) {
             return false;
         }
-        getAccessibilityPrefetchStrategy().onAccessibilityEvent(event);
         mAccessibilityManager.sendAccessibilityEvent(event);
         return true;
     }
@@ -4680,12 +4689,12 @@
 
         public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
                 int interactionId, IAccessibilityInteractionConnectionCallback callback,
-                int interrogatingPid, long interrogatingTid) {
+                int prefetchFlags, int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
-                        interactionId, callback, interrogatingPid, interrogatingTid);
+                        interactionId, callback, prefetchFlags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -4820,11 +4829,11 @@
 
         public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
                 long accessibilityNodeId, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
-                long interrogatingTid) {
+                IAccessibilityInteractionConnectionCallback callback, int prefetchFlags,
+                int interrogatingPid, long interrogatingTid) {
             Message message = mHandler.obtainMessage();
             message.what = MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
-            message.arg1 = interrogatingPid;
+            message.arg1 = prefetchFlags;
             SomeArgs args = mPool.acquire();
             args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
             args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
@@ -4845,8 +4854,8 @@
         }
 
         public void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
+            final int prefetchFlags = message.arg1;
             SomeArgs args = (SomeArgs) message.obj;
-            final int interrogatingPid = message.arg1;
             final int accessibilityViewId = args.argi1;
             final int virtualDescendantId = args.argi2;
             final int interactionId = args.argi3;
@@ -4856,22 +4865,15 @@
             List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
             infos.clear();
             try {
+                View target = null;
                 if (accessibilityViewId == AccessibilityNodeInfo.UNDEFINED) {
-                    View target = ViewRootImpl.this.mView;
-                    if (target != null && target.getVisibility() == View.VISIBLE) {
-                        infos.add(target.createAccessibilityNodeInfo());
-                    }
+                    target = ViewRootImpl.this.mView;
                 } else {
-                    View target = findViewByAccessibilityId(accessibilityViewId);
-                    if (target != null && target.getVisibility() == View.VISIBLE) {
-                        AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
-                        if (provider != null) {
-                            infos.add(provider.createAccessibilityNodeInfo(virtualDescendantId));
-                        } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED) {
-                            getAccessibilityPrefetchStrategy().prefetchAccessibilityNodeInfos(
-                                    interrogatingPid, target, infos);
-                        }
-                    }
+                    target = findViewByAccessibilityId(accessibilityViewId);
+                }
+                if (target != null && target.getVisibility() == View.VISIBLE) {
+                    getAccessibilityNodePrefetcher().prefetchAccessibilityNodeInfos(target,
+                            virtualDescendantId, prefetchFlags, infos);
                 }
             } finally {
                 try {
@@ -5132,83 +5134,216 @@
 
     /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
-     * querying window content.It is responsible to prefetch a batch of
-     * AccessibilityNodeInfos in addition to the one for a requested node. It caches
-     * the ids of the prefeteched nodes such that they are fetched only once.
+     * querying window content. It is responsible to prefetch a batch of
+     * AccessibilityNodeInfos in addition to the one for a requested node.
      */
-    class AccessibilityPrefetchStrategy {
-        private static final int MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE = 100;
+    class AccessibilityNodePrefetcher {
 
-        // We need to keep track of what we have sent for each interrogating
-        // process. Usually there will be only one such process but we
-        // should support the general case. Note that the accessibility event
-        // stream will take care of clearing caches of querying processes that
-        // are not longer alive, so we do not waste memory.
-        private final LongSparseArray<AccessibilityNodeInfoCache> mAccessibilityNodeInfoCaches =
-            new LongSparseArray<AccessibilityNodeInfoCache>();
+        private static final int MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE = 50;
 
-        private AccessibilityNodeInfoCache getCacheForInterrogatingPid(long interrogatingPid) {
-            AccessibilityNodeInfoCache cache = mAccessibilityNodeInfoCaches.get(interrogatingPid);
-            if (cache == null) {
-                cache = AccessibilityNodeInfoCache.newAccessibilityNodeInfoCache();
-                mAccessibilityNodeInfoCaches.put(interrogatingPid, cache);
-            }
-            return cache;
-        }
-
-        public void onAccessibilityEvent(AccessibilityEvent event) {
-            final int cacheCount = mAccessibilityNodeInfoCaches.size();
-            for (int i = 0; i < cacheCount; i++) {
-                AccessibilityNodeInfoCache cache = mAccessibilityNodeInfoCaches.valueAt(i);
-                cache.onAccessibilityEvent(event);
-            }
-        }
-
-        public void prefetchAccessibilityNodeInfos(long interrogatingPid, View root,
+        public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int prefetchFlags,
                 List<AccessibilityNodeInfo> outInfos) {
-            addAndCacheNotCachedNodeInfo(interrogatingPid, root, outInfos);
-            addAndCacheNotCachedPredecessorInfos(interrogatingPid, root, outInfos);
-            addAndCacheNotCachedDescendantInfos(interrogatingPid, root, outInfos);
-        }
-
-        private void addAndCacheNotCachedNodeInfo(long interrogatingPid,
-                View view, List<AccessibilityNodeInfo> outInfos) {
-            final long accessibilityNodeId = AccessibilityNodeInfo.makeNodeId(
-                    view.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
-            AccessibilityNodeInfoCache cache = getCacheForInterrogatingPid(interrogatingPid);
-            if (!cache.containsKey(accessibilityNodeId)) {
-                // Account for the ids of the fetched infos. The infos will be
-                // cached in the window querying process. We just need to know
-                // which infos are cached to avoid fetching a cached one again.
-                cache.put(accessibilityNodeId, null);
-                outInfos.add(view.createAccessibilityNodeInfo());
+            AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+            if (provider == null) {
+                AccessibilityNodeInfo root = view.createAccessibilityNodeInfo();
+                if (root != null) {
+                    outInfos.add(root);
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
+                        prefetchPredecessorsOfRealNode(view, outInfos);
+                    }
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0) {
+                        prefetchSiblingsOfRealNode(view, outInfos);
+                    }
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) {
+                        prefetchDescendantsOfRealNode(view, outInfos);
+                    }
+                }
+            } else {
+                AccessibilityNodeInfo root = provider.createAccessibilityNodeInfo(virtualViewId);
+                if (root != null) {
+                    outInfos.add(root);
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
+                        prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos);
+                    }
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0) {
+                        prefetchSiblingsOfVirtualNode(root, view, provider, outInfos);
+                    }
+                    if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) {
+                        prefetchDescendantsOfVirtualNode(root, provider, outInfos);
+                    }
+                }
             }
         }
 
-        private void addAndCacheNotCachedPredecessorInfos(long interrogatingPid, View view,
+        private void prefetchPredecessorsOfRealNode(View view,
                 List<AccessibilityNodeInfo> outInfos) {
-            ViewParent predecessor = view.getParent();
-            while (predecessor instanceof View
+            ViewParent parent = view.getParent();
+            while (parent instanceof View
                     && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
-                View predecessorView = (View) predecessor;
-                addAndCacheNotCachedNodeInfo(interrogatingPid, predecessorView, outInfos);
-                predecessor = predecessor.getParent();
+                View parentView = (View) parent;
+                final long parentNodeId = AccessibilityNodeInfo.makeNodeId(
+                        parentView.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
+                AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo();
+                if (info != null) {
+                    outInfos.add(info);
+                }
+                parent = parent.getParent();
             }
         }
 
-        private void addAndCacheNotCachedDescendantInfos(long interrogatingPid, View view,
+        private void prefetchSiblingsOfRealNode(View current,
                 List<AccessibilityNodeInfo> outInfos) {
-            if (outInfos.size() > MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE
-                    || view.getAccessibilityNodeProvider() != null) {
-                return;
+            ViewParent parent = current.getParent();
+            if (parent instanceof ViewGroup) {
+                ViewGroup parentGroup = (ViewGroup) parent;
+                final int childCount = parentGroup.getChildCount();
+                for (int i = 0; i < childCount; i++) {
+                    View child = parentGroup.getChildAt(i);
+                    if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE
+                            && child.getAccessibilityViewId() != current.getAccessibilityViewId()
+                            && child.getVisibility() == View.VISIBLE) {
+                        final long childNodeId = AccessibilityNodeInfo.makeNodeId(
+                                child.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
+                        AccessibilityNodeInfo info = null;
+                        AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
+                        if (provider == null) {
+                            info = child.createAccessibilityNodeInfo();
+                        } else {
+                            info = provider.createAccessibilityNodeInfo(
+                                    AccessibilityNodeInfo.UNDEFINED);
+                        }
+                        if (info != null) {
+                            outInfos.add(info);
+                        }
+                    }
+                }
             }
-            addAndCacheNotCachedNodeInfo(interrogatingPid, view, outInfos);
-            if (view instanceof ViewGroup) {
-                ViewGroup rootGroup = (ViewGroup) view;
+        }
+
+        private void prefetchDescendantsOfRealNode(View root,
+                List<AccessibilityNodeInfo> outInfos) {
+            if (root instanceof ViewGroup) {
+                ViewGroup rootGroup = (ViewGroup) root;
+                HashMap<View, AccessibilityNodeInfo> addedChildren =
+                    new HashMap<View, AccessibilityNodeInfo>();
                 final int childCount = rootGroup.getChildCount();
                 for (int i = 0; i < childCount; i++) {
-                View child = rootGroup.getChildAt(i);
-                    addAndCacheNotCachedDescendantInfos(interrogatingPid, child, outInfos);
+                    View child = rootGroup.getChildAt(i);
+                    if (child.getVisibility() == View.VISIBLE
+                            && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                        final long childNodeId = AccessibilityNodeInfo.makeNodeId(
+                                child.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
+                        AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
+                        if (provider == null) {
+                            AccessibilityNodeInfo info = child.createAccessibilityNodeInfo();
+                            if (info != null) {
+                                outInfos.add(info);
+                                addedChildren.put(child, null);
+                            }
+                        } else {
+                            AccessibilityNodeInfo info = provider.createAccessibilityNodeInfo(
+                                   AccessibilityNodeInfo.UNDEFINED);
+                            if (info != null) {
+                                outInfos.add(info);
+                                addedChildren.put(child, info);
+                            }
+                        }
+                    }
+                }
+                if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                    for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
+                        View addedChild = entry.getKey();
+                        AccessibilityNodeInfo virtualRoot = entry.getValue();
+                        if (virtualRoot == null) {
+                            prefetchDescendantsOfRealNode(addedChild, outInfos);
+                        } else {
+                            AccessibilityNodeProvider provider =
+                                addedChild.getAccessibilityNodeProvider();
+                            prefetchDescendantsOfVirtualNode(virtualRoot, provider, outInfos);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void prefetchPredecessorsOfVirtualNode(AccessibilityNodeInfo root,
+                View providerHost, AccessibilityNodeProvider provider,
+                List<AccessibilityNodeInfo> outInfos) {
+            long parentNodeId = root.getParentNodeId();
+            int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
+            while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED) {
+                final int virtualDescendantId =
+                    AccessibilityNodeInfo.getVirtualDescendantId(parentNodeId);
+                if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED
+                        || accessibilityViewId == providerHost.getAccessibilityViewId()) {
+                    AccessibilityNodeInfo parent = provider.createAccessibilityNodeInfo(
+                            virtualDescendantId);
+                    if (parent != null) {
+                        outInfos.add(parent);
+                    }
+                    parentNodeId = parent.getParentNodeId();
+                    accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
+                            parentNodeId);
+                } else {
+                    prefetchPredecessorsOfRealNode(providerHost, outInfos);
+                    return;
+                }
+            }
+        }
+
+        private void prefetchSiblingsOfVirtualNode(AccessibilityNodeInfo current, View providerHost,
+                AccessibilityNodeProvider provider, List<AccessibilityNodeInfo> outInfos) {
+            final long parentNodeId = current.getParentNodeId();
+            final int parentAccessibilityViewId =
+                AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
+            final int parentVirtualDescendantId =
+                AccessibilityNodeInfo.getVirtualDescendantId(parentNodeId);
+            if (parentVirtualDescendantId != AccessibilityNodeInfo.UNDEFINED
+                    || parentAccessibilityViewId == providerHost.getAccessibilityViewId()) {
+                AccessibilityNodeInfo parent =
+                    provider.createAccessibilityNodeInfo(parentVirtualDescendantId);
+                if (parent != null) {
+                    SparseLongArray childNodeIds = parent.getChildNodeIds();
+                    final int childCount = childNodeIds.size();
+                    for (int i = 0; i < childCount; i++) {
+                        final long childNodeId = childNodeIds.get(i);
+                        if (childNodeId != current.getSourceNodeId()
+                                && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                            final int childVirtualDescendantId =
+                                AccessibilityNodeInfo.getVirtualDescendantId(childNodeId);
+                            AccessibilityNodeInfo child = provider.createAccessibilityNodeInfo(
+                                    childVirtualDescendantId);
+                            if (child != null) {
+                                outInfos.add(child);
+                            }
+                        }
+                    }
+                }
+            } else {
+                prefetchSiblingsOfRealNode(providerHost, outInfos);
+            }
+        }
+
+        private void prefetchDescendantsOfVirtualNode(AccessibilityNodeInfo root,
+                AccessibilityNodeProvider provider, List<AccessibilityNodeInfo> outInfos) {
+            SparseLongArray childNodeIds = root.getChildNodeIds();
+            final int initialOutInfosSize = outInfos.size();
+            final int childCount = childNodeIds.size();
+            for (int i = 0; i < childCount; i++) {
+                if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                    final long childNodeId = childNodeIds.get(i);
+                    AccessibilityNodeInfo child = provider.createAccessibilityNodeInfo(
+                            AccessibilityNodeInfo.getVirtualDescendantId(childNodeId));
+                    if (child != null) {
+                        outInfos.add(child);
+                    }
+                }
+            }
+            if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+                final int addedChildCount = outInfos.size() - initialOutInfosSize;
+                for (int i = 0; i < addedChildCount; i++) {
+                    AccessibilityNodeInfo child = outInfos.get(initialOutInfosSize + i);
+                    prefetchDescendantsOfVirtualNode(child, provider, outInfos);
                 }
             }
         }
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 105c010..be74b31 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -24,7 +24,6 @@
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.SparseArray;
-import android.view.AccessibilityNodeInfoCache;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -102,7 +101,7 @@
     // The connection cache is shared between all interrogating threads since
     // at any given time there is only one window allowing querying.
     private static final AccessibilityNodeInfoCache sAccessibilityNodeInfoCache =
-        AccessibilityNodeInfoCache.newSynchronizedAccessibilityNodeInfoCache();
+        new AccessibilityNodeInfoCache();
 
     /**
      * @return The client for the current thread.
@@ -159,10 +158,11 @@
      *     where to start the search. Use
      *     {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
      *     to start from the root.
+     * @param prefetchFlags flags to guide prefetching.
      * @return An {@link AccessibilityNodeInfo} if found, null otherwise.
      */
     public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
-            int accessibilityWindowId, long accessibilityNodeId) {
+            int accessibilityWindowId, long accessibilityNodeId, int prefetchFlags) {
         try {
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
@@ -174,7 +174,7 @@
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
                         accessibilityWindowId, accessibilityNodeId, interactionId, this,
-                        Thread.currentThread().getId());
+                        Thread.currentThread().getId(), prefetchFlags);
                 // If the scale is zero the call has failed.
                 if (windowScale > 0) {
                     List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 84ad268..c094fda 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -61,6 +61,15 @@
     /** @hide */
     public static final int ACTIVE_WINDOW_ID = UNDEFINED;
 
+    /** @hide */
+    public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
+
+    /** @hide */
+    public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
+
+    /** @hide */
+    public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000003;
+
     // Actions.
 
     /**
@@ -181,7 +190,7 @@
     private CharSequence mText;
     private CharSequence mContentDescription;
 
-    private SparseLongArray mChildIds = new SparseLongArray();
+    private SparseLongArray mChildNodeIds = new SparseLongArray();
     private int mActions;
 
     private int mConnectionId = UNDEFINED;
@@ -244,12 +253,21 @@
     }
 
     /**
+     * @return The ids of the children.
+     *
+     * @hide
+     */
+    public SparseLongArray getChildNodeIds() {
+        return mChildNodeIds;
+    }
+
+    /**
      * Gets the number of children.
      *
      * @return The child count.
      */
     public int getChildCount() {
-        return mChildIds.size();
+        return mChildNodeIds.size();
     }
 
     /**
@@ -271,9 +289,10 @@
         if (!canPerformRequestOverConnection(mSourceNodeId)) {
             return null;
         }
-        final long childId = mChildIds.get(index);
+        final long childId = mChildNodeIds.get(index);
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId, childId);
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
+                childId, FLAG_PREFETCH_DESCENDANTS);
     }
 
     /**
@@ -308,11 +327,11 @@
      */
     public void addChild(View root, int virtualDescendantId) {
         enforceNotSealed();
-        final int index = mChildIds.size();
+        final int index = mChildNodeIds.size();
         final int rootAccessibilityViewId =
             (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
         final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
-        mChildIds.put(index, childNodeId);
+        mChildNodeIds.put(index, childNodeId);
     }
 
     /**
@@ -408,7 +427,16 @@
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
-                mWindowId, mParentNodeId);
+                mWindowId, mParentNodeId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+    }
+
+    /**
+     * @return The parent node id.
+     *
+     * @hide
+     */
+    public long getParentNodeId() {
+        return mParentNodeId;
     }
 
     /**
@@ -1070,7 +1098,7 @@
         parcel.writeLong(mParentNodeId);
         parcel.writeInt(mConnectionId);
 
-        SparseLongArray childIds = mChildIds;
+        SparseLongArray childIds = mChildNodeIds;
         final int childIdsSize = childIds.size();
         parcel.writeInt(childIdsSize);
         for (int i = 0; i < childIdsSize; i++) {
@@ -1120,7 +1148,7 @@
         mContentDescription = other.mContentDescription;
         mActions= other.mActions;
         mBooleanProperties = other.mBooleanProperties;
-        mChildIds = other.mChildIds.clone();
+        mChildNodeIds = other.mChildNodeIds.clone();
     }
 
     /**
@@ -1135,7 +1163,7 @@
         mParentNodeId = parcel.readLong();
         mConnectionId = parcel.readInt();
 
-        SparseLongArray childIds = mChildIds;
+        SparseLongArray childIds = mChildNodeIds;
         final int childrenSize = parcel.readInt();
         for (int i = 0; i < childrenSize; i++) {
             final long childId = parcel.readLong();
@@ -1171,7 +1199,7 @@
         mParentNodeId = ROOT_NODE_ID;
         mWindowId = UNDEFINED;
         mConnectionId = UNDEFINED;
-        mChildIds.clear();
+        mChildNodeIds.clear();
         mBoundsInParent.set(0, 0, 0, 0);
         mBoundsInScreen.set(0, 0, 0, 0);
         mBooleanProperties = 0;
@@ -1249,7 +1277,7 @@
             builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
             builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
             builder.append("; mParentNodeId: " + mParentNodeId);
-            SparseLongArray childIds = mChildIds;
+            SparseLongArray childIds = mChildNodeIds;
             builder.append("; childAccessibilityIds: [");
             for (int i = 0, count = childIds.size(); i < count; i++) {
                 builder.append(childIds.valueAt(i));
diff --git a/core/java/android/view/AccessibilityNodeInfoCache.java b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
similarity index 61%
rename from core/java/android/view/AccessibilityNodeInfoCache.java
rename to core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
index 84b510d..4fb0046 100644
--- a/core/java/android/view/AccessibilityNodeInfoCache.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.view.accessibility;
 
 import android.os.Process;
 import android.util.Log;
 import android.util.LongSparseArray;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * Simple cache for AccessibilityNodeInfos. The cache is mapping an
@@ -38,53 +36,11 @@
 
     private static final boolean DEBUG = false;
 
-    /**
-     * @return A new <strong>not synchronized</strong> AccessibilityNodeInfoCache.
-     */
-    public static AccessibilityNodeInfoCache newAccessibilityNodeInfoCache() {
-        return new AccessibilityNodeInfoCache();
-    }
-
-    /**
-     * @return A new <strong>synchronized</strong> AccessibilityNodeInfoCache.
-     */
-    public static AccessibilityNodeInfoCache newSynchronizedAccessibilityNodeInfoCache() {
-        return new AccessibilityNodeInfoCache() {
-            private final Object mLock = new Object();
-
-            @Override
-            public void clear() {
-                synchronized(mLock) {
-                    super.clear();
-                }
-            }
-
-            @Override
-            public AccessibilityNodeInfo get(long accessibilityNodeId) {
-                synchronized(mLock) {
-                    return super.get(accessibilityNodeId);
-                }
-            }
-
-            @Override
-            public void put(long accessibilityNodeId, AccessibilityNodeInfo info) {
-                synchronized(mLock) {
-                   super.put(accessibilityNodeId, info);
-                }
-            }
-
-            @Override
-            public void remove(long accessibilityNodeId) {
-                synchronized(mLock) {
-                   super.remove(accessibilityNodeId);
-                }
-            }
-        };
-    }
+    private final Object mLock = new Object();
 
     private final LongSparseArray<AccessibilityNodeInfo> mCacheImpl;
 
-    private AccessibilityNodeInfoCache() {
+    public AccessibilityNodeInfoCache() {
         if (ENABLED) {
             mCacheImpl = new LongSparseArray<AccessibilityNodeInfo>();
         } else {
@@ -124,13 +80,15 @@
      */
     public AccessibilityNodeInfo get(long accessibilityNodeId) {
         if (ENABLED) {
-            if (DEBUG) {
-                AccessibilityNodeInfo info = mCacheImpl.get(accessibilityNodeId);
-                Log.i(LOG_TAG, "Process: " + Process.myPid() +
-                        " get(" + accessibilityNodeId + ") = " + info);
-                return info;
-            } else {
-                return mCacheImpl.get(accessibilityNodeId);
+            synchronized(mLock) {
+                if (DEBUG) {
+                    AccessibilityNodeInfo info = mCacheImpl.get(accessibilityNodeId);
+                    Log.i(LOG_TAG, "Process: " + Process.myPid() +
+                            " get(" + accessibilityNodeId + ") = " + info);
+                    return info;
+                } else {
+                    return mCacheImpl.get(accessibilityNodeId);
+                }
             }
         } else {
             return null;
@@ -145,11 +103,13 @@
      */
     public void put(long accessibilityNodeId, AccessibilityNodeInfo info) {
         if (ENABLED) {
-            if (DEBUG) {
-                Log.i(LOG_TAG, "Process: " + Process.myPid()
-                        + " put(" + accessibilityNodeId + ", " + info + ")");
+            synchronized(mLock) {
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "Process: " + Process.myPid()
+                            + " put(" + accessibilityNodeId + ", " + info + ")");
+                }
+                mCacheImpl.put(accessibilityNodeId, info);
             }
-            mCacheImpl.put(accessibilityNodeId, info);
         }
     }
 
@@ -161,7 +121,9 @@
      */
     public boolean containsKey(long accessibilityNodeId) {
         if (ENABLED) {
-            return (mCacheImpl.indexOfKey(accessibilityNodeId) >= 0);
+            synchronized(mLock) {
+                return (mCacheImpl.indexOfKey(accessibilityNodeId) >= 0);
+            }
         } else {
             return false;
         }
@@ -174,11 +136,13 @@
      */
     public void remove(long accessibilityNodeId) {
         if (ENABLED) {
-            if (DEBUG) {
-                Log.i(LOG_TAG,  "Process: " + Process.myPid()
-                        + " remove(" + accessibilityNodeId + ")");
+            synchronized(mLock) {
+                if (DEBUG) {
+                    Log.i(LOG_TAG,  "Process: " + Process.myPid()
+                            + " remove(" + accessibilityNodeId + ")");
+                }
+                mCacheImpl.remove(accessibilityNodeId);
             }
-            mCacheImpl.remove(accessibilityNodeId);
         }
     }
 
@@ -187,10 +151,12 @@
      */
     public void clear() {
         if (ENABLED) {
-            if (DEBUG) {
-                Log.i(LOG_TAG,  "Process: " + Process.myPid() + "clear()");
+            synchronized(mLock) {
+                if (DEBUG) {
+                    Log.i(LOG_TAG,  "Process: " + Process.myPid() + "clear()");
+                }
+                mCacheImpl.clear();
             }
-            mCacheImpl.clear();
         }
     }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index b60f50e..23b235c 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -56,6 +56,11 @@
     private static final int PROPERTY_FULL_SCREEN = 0x00000080;
     private static final int PROPERTY_SCROLLABLE = 0x00000100;
 
+    private static final int GET_SOURCE_PREFETCH_FLAGS =
+        AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS
+        | AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
+        | AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS;
+
     // Housekeeping
     private static final int MAX_POOL_SIZE = 10;
     private static final Object sPoolLock = new Object();
@@ -144,7 +149,7 @@
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
-                mSourceNodeId);
+                mSourceNodeId, GET_SOURCE_PREFETCH_FLAGS);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index ae6869c..fc3651c 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -28,7 +28,7 @@
 oneway interface IAccessibilityInteractionConnection {
 
     void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback,
+        IAccessibilityInteractionConnectionCallback callback, int prefetchFlags,
         int interrogatingPid, long interrogatingTid);
 
     void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int id, int interactionId,
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5601dca..98d59c4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -122,6 +122,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -555,17 +556,13 @@
                         && TextUtils.regionMatches(text, 0, original, 0,
                                 textLength);
             }
-            boolean sendChange = false;
             if (isCharacterAdd) {
-                sendChange = !sendCharacter(text.charAt(textLength - 1));
+                sendCharacter(text.charAt(textLength - 1));
             } else if (isCharacterDelete) {
                 sendDeleteKey();
-            } else {
-                sendChange = (textLength != originalLength) ||
-                        !TextUtils.regionMatches(text, 0, original, 0,
-                                textLength);
-            }
-            if (sendChange) {
+            } else if ((textLength != originalLength) ||
+                    !TextUtils.regionMatches(text, 0, original, 0,
+                            textLength)) {
                 // Send a message so that key strokes and text replacement
                 // do not come out of order.
                 Message replaceMessage = mPrivateHandler.obtainMessage(
@@ -579,20 +576,21 @@
          * Send a single character to the WebView as a key down and up event.
          * @param c The character to be sent.
          */
-        private boolean sendCharacter(char c) {
+        private void sendCharacter(char c) {
             if (mKeyCharacterMap == null) {
                 mKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
             }
             char[] chars = new char[1];
             chars[0] = c;
             KeyEvent[] events = mKeyCharacterMap.getEvents(chars);
-            boolean mapsToKeyEvent = (events != null);
-            if (mapsToKeyEvent) {
+            if (events != null) {
                 for (KeyEvent event : events) {
                     sendKeyEvent(event);
                 }
+            } else {
+                Message msg = mPrivateHandler.obtainMessage(KEY_PRESS, (int) c, 0);
+                mPrivateHandler.sendMessage(msg);
             }
-            return mapsToKeyEvent;
         }
 
         /**
@@ -1030,6 +1028,7 @@
     static final int INIT_EDIT_FIELD                    = 142;
     static final int REPLACE_TEXT                       = 143;
     static final int CLEAR_CARET_HANDLE                 = 144;
+    static final int KEY_PRESS                          = 145;
 
     private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
     private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
@@ -7922,7 +7921,10 @@
                 }
             }, ViewConfiguration.getPressedStateDuration());
         }
-        if (sDisableNavcache) {
+        if (mFocusedNode != null && mFocusedNode.mIntentUrl != null) {
+            playSoundEffect(SoundEffectConstants.CLICK);
+            overrideLoading(mFocusedNode.mIntentUrl);
+        } else if (sDisableNavcache) {
             WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
             // use "0" as generation id to inform WebKit to use the same x/y as
             // it used when processing GET_TOUCH_HIGHLIGHT_RECTS
@@ -9160,24 +9162,7 @@
                     WebKitHitTest hit = (WebKitHitTest) msg.obj;
                     mFocusedNode = hit;
                     setTouchHighlightRects(hit);
-                    if (hit == null) {
-                        mInitialHitTestResult = null;
-                    } else {
-                        mInitialHitTestResult = new HitTestResult();
-                        if (hit.mLinkUrl != null) {
-                            mInitialHitTestResult.mType = HitTestResult.SRC_ANCHOR_TYPE;
-                            mInitialHitTestResult.mExtra = hit.mLinkUrl;
-                            if (hit.mImageUrl != null) {
-                                mInitialHitTestResult.mType = HitTestResult.SRC_IMAGE_ANCHOR_TYPE;
-                                mInitialHitTestResult.mExtra = hit.mImageUrl;
-                            }
-                        } else if (hit.mImageUrl != null) {
-                            mInitialHitTestResult.mType = HitTestResult.IMAGE_TYPE;
-                            mInitialHitTestResult.mExtra = hit.mImageUrl;
-                        } else if (hit.mEditable) {
-                            mInitialHitTestResult.mType = HitTestResult.EDIT_TEXT_TYPE;
-                        }
-                    }
+                    setHitTestResult(hit);
                     break;
 
                 case SAVE_WEBARCHIVE_FINISHED:
@@ -9242,6 +9227,10 @@
                     selectionDone();
                     break;
 
+                case KEY_PRESS:
+                    mWebViewCore.sendMessage(EventHub.KEY_PRESS, msg.arg1);
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -9249,6 +9238,47 @@
         }
     }
 
+    private void setHitTestResult(WebKitHitTest hit) {
+        if (hit == null) {
+            mInitialHitTestResult = null;
+            return;
+        }
+        mInitialHitTestResult = new HitTestResult();
+        if (hit.mLinkUrl != null) {
+            mInitialHitTestResult.mType = HitTestResult.SRC_ANCHOR_TYPE;
+            mInitialHitTestResult.mExtra = hit.mLinkUrl;
+            if (hit.mImageUrl != null) {
+                mInitialHitTestResult.mType = HitTestResult.SRC_IMAGE_ANCHOR_TYPE;
+                mInitialHitTestResult.mExtra = hit.mImageUrl;
+            }
+        } else if (hit.mImageUrl != null) {
+            mInitialHitTestResult.mType = HitTestResult.IMAGE_TYPE;
+            mInitialHitTestResult.mExtra = hit.mImageUrl;
+        } else if (hit.mEditable) {
+            mInitialHitTestResult.mType = HitTestResult.EDIT_TEXT_TYPE;
+        } else if (hit.mIntentUrl != null) {
+            String substr = null;
+            if (hit.mIntentUrl.startsWith(SCHEME_GEO)) {
+                mInitialHitTestResult.mType = HitTestResult.GEO_TYPE;
+                substr = hit.mIntentUrl.substring(SCHEME_GEO.length());
+            } else if (hit.mIntentUrl.startsWith(SCHEME_TEL)) {
+                mInitialHitTestResult.mType = HitTestResult.PHONE_TYPE;
+                substr = hit.mIntentUrl.substring(SCHEME_TEL.length());
+            } else if (hit.mIntentUrl.startsWith(SCHEME_MAILTO)) {
+                mInitialHitTestResult.mType = HitTestResult.EMAIL_TYPE;
+                substr = hit.mIntentUrl.substring(SCHEME_MAILTO.length());
+            } else {
+                return;
+            }
+            try {
+                mInitialHitTestResult.mExtra = URLDecoder.decode(substr, "UTF-8");
+            } catch (Throwable e) {
+                Log.w(LOGTAG, "Failed to decode GEO URL!", e);
+                mInitialHitTestResult.mType = HitTestResult.UNKNOWN_TYPE;
+            }
+        }
+    }
+
     private boolean shouldDrawHighlightRect() {
         if (mFocusedNode == null || mInitialHitTestResult == null) {
             return false;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 037e323..e7da1a8 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -879,6 +879,7 @@
 
     static class WebKitHitTest {
         String mLinkUrl;
+        String mIntentUrl;
         String mAnchorText;
         String mImageUrl;
         String mAltDisplayString;
@@ -1172,8 +1173,11 @@
         static final int TRUST_STORAGE_UPDATED = 220;
 
         // find-on-page controls
-        static final int FIND_ALL = 220;
-        static final int FIND_NEXT = 221;
+        static final int FIND_ALL = 221;
+        static final int FIND_NEXT = 222;
+
+        // key was pressed (down and up)
+        static final int KEY_PRESS = 223;
 
         // Private handler for WebCore messages.
         private Handler mHandler;
@@ -1354,6 +1358,10 @@
                             key((KeyEvent) msg.obj, false);
                             break;
 
+                        case KEY_PRESS:
+                            keyPress(msg.arg1);
+                            break;
+
                         case FAKE_CLICK:
                             nativeClick(mNativeClass, msg.arg1, msg.arg2, true);
                             break;
@@ -2060,6 +2068,11 @@
         }
     }
 
+    private void keyPress(int unicodeChar) {
+        nativeKey(mNativeClass, 0, unicodeChar, 0, false, false, false, true);
+        nativeKey(mNativeClass, 0, unicodeChar, 0, false, false, false, false);
+    }
+
     // These values are used to avoid requesting a layout based on old values
     private int mCurrentViewWidth = 0;
     private int mCurrentViewHeight = 0;
diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd
index 85599f7..e969f5d 100644
--- a/docs/html/sdk/ndk/overview.jd
+++ b/docs/html/sdk/ndk/overview.jd
@@ -46,7 +46,7 @@
     <li>Documentation, samples, and tutorials</li>
   </ul>
 
-  <p>The latest release of the NDK supports these ARM instruction sets:</p>
+  <p>The latest release of the NDK supports the following instruction sets:</p>
 
   <ul>
     <li>ARMv5TE (including Thumb-1 instructions)</li>
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 0ada1fb..ec911b0 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -352,8 +352,7 @@
                // check for empty first
         return this.left < this.right && this.top < this.bottom
                // now check for containment
-               && left <= r.left && top <= r.top
-               && right >= r.right && bottom >= r.bottom;
+               && left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom;
     }
 
     /**
@@ -375,20 +374,11 @@
      *              return false and do not change this rectangle.
      */
     public boolean intersect(int left, int top, int right, int bottom) {
-        if (this.left < right && left < this.right
-                && this.top < bottom && top < this.bottom) {
-            if (this.left < left) {
-                this.left = left;
-            }
-            if (this.top < top) {
-                this.top = top;
-            }
-            if (this.right > right) {
-                this.right = right;
-            }
-            if (this.bottom > bottom) {
-                this.bottom = bottom;
-            }
+        if (this.left < right && left < this.right && this.top < bottom && top < this.bottom) {
+            if (this.left < left) this.left = left;
+            if (this.top < top) this.top = top;
+            if (this.right > right) this.right = right;
+            if (this.bottom > bottom) this.bottom = bottom;
             return true;
         }
         return false;
@@ -422,8 +412,7 @@
      *              false and do not change this rectangle.
      */
     public boolean setIntersect(Rect a, Rect b) {
-        if (a.left < b.right && b.left < a.right
-                && a.top < b.bottom && b.top < a.bottom) {
+        if (a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom) {
             left = Math.max(a.left, b.left);
             top = Math.max(a.top, b.top);
             right = Math.min(a.right, b.right);
@@ -448,8 +437,7 @@
      *              no event is this rectangle modified.
      */
     public boolean intersects(int left, int top, int right, int bottom) {
-        return this.left < right && left < this.right
-               && this.top < bottom && top < this.bottom;
+        return this.left < right && left < this.right && this.top < bottom && top < this.bottom;
     }
 
     /**
@@ -463,8 +451,7 @@
      *              either of the rectangles modified.
      */
     public static boolean intersects(Rect a, Rect b) {
-        return a.left < b.right && b.left < a.right
-               && a.top < b.bottom && b.top < a.bottom;
+        return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;
     }
 
     /**
@@ -480,14 +467,10 @@
     public void union(int left, int top, int right, int bottom) {
         if ((left < right) && (top < bottom)) {
             if ((this.left < this.right) && (this.top < this.bottom)) {
-                if (this.left > left)
-                    this.left = left;
-                if (this.top > top)
-                    this.top = top;
-                if (this.right < right)
-                    this.right = right;
-                if (this.bottom < bottom)
-                    this.bottom = bottom;
+                if (this.left > left) this.left = left;
+                if (this.top > top) this.top = top;
+                if (this.right < right) this.right = right;
+                if (this.bottom < bottom) this.bottom = bottom;
             } else {
                 this.left = left;
                 this.top = top;
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 37a270e..6539ff3 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -534,6 +534,7 @@
      * @param fp
      */
     public void setFromFieldPacker(int xoff, FieldPacker fp) {
+        mRS.validate();
         int eSize = mType.mElement.getSizeBytes();
         final byte[] data = fp.getData();
 
@@ -554,6 +555,7 @@
      * @param fp
      */
     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
+        mRS.validate();
         if (component_number >= mType.mElement.mElements.length) {
             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
         }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 90a7145..4a299c6 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -462,6 +462,7 @@
         SkPath* pathCopy = mPathMap.valueFor(path);
         if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
             pathCopy = new SkPath(*path);
+            pathCopy->setSourcePath(path);
             // replaceValueFor() performs an add if the entry doesn't exist
             mPathMap.replaceValueFor(path, pathCopy);
             mPaths.add(pathCopy);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index e09c243..e363b73 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -83,6 +83,11 @@
 }
 
 PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
+    const SkPath* sourcePath = path->getSourcePath();
+    if (sourcePath && sourcePath->getGenerationID() == path->getGenerationID()) {
+        path = const_cast<SkPath*>(sourcePath);
+    }
+
     PathCacheEntry entry(path, paint);
     PathTexture* texture = mCache.get(entry);
 
diff --git a/libs/rs/Allocation.cpp b/libs/rs/Allocation.cpp
new file mode 100644
index 0000000..46df171
--- /dev/null
+++ b/libs/rs/Allocation.cpp
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+#include <malloc.h>
+
+#include "RenderScript.h"
+#include "Element.h"
+#include "Type.h"
+#include "Allocation.h"
+
+
+void * Allocation::getIDSafe() const {
+    //if (mAdaptedAllocation != NULL) {
+        //return mAdaptedAllocation.getID();
+    //}
+    return getID();
+}
+
+void Allocation::updateCacheInfo(const Type *t) {
+    mCurrentDimX = t->getX();
+    mCurrentDimY = t->getY();
+    mCurrentDimZ = t->getZ();
+    mCurrentCount = mCurrentDimX;
+    if (mCurrentDimY > 1) {
+        mCurrentCount *= mCurrentDimY;
+    }
+    if (mCurrentDimZ > 1) {
+        mCurrentCount *= mCurrentDimZ;
+    }
+}
+
+Allocation::Allocation(void *id, RenderScript *rs, const Type *t, uint32_t usage) : BaseObj(id, rs) {
+    if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT |
+                   RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
+                   RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
+                   RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
+                   RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
+                   RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
+                   RS_ALLOCATION_USAGE_IO_INPUT |
+                   RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
+        ALOGE("Unknown usage specified.");
+    }
+
+    if ((usage & (RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
+                  RS_ALLOCATION_USAGE_IO_INPUT)) != 0) {
+        mWriteAllowed = false;
+        if ((usage & ~(RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
+                       RS_ALLOCATION_USAGE_IO_INPUT |
+                       RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
+                       RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
+            ALOGE("Invalid usage combination.");
+        }
+    }
+
+    mType = t;
+    mUsage = usage;
+
+    if (t != NULL) {
+        updateCacheInfo(t);
+    }
+}
+
+void Allocation::validateIsInt32() {
+    RsDataType dt = mType->getElement()->getDataType();
+    if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
+        return;
+    }
+    ALOGE("32 bit integer source does not match allocation type %i", dt);
+}
+
+void Allocation::validateIsInt16() {
+    RsDataType dt = mType->getElement()->getDataType();
+    if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
+        return;
+    }
+    ALOGE("16 bit integer source does not match allocation type %i", dt);
+}
+
+void Allocation::validateIsInt8() {
+    RsDataType dt = mType->getElement()->getDataType();
+    if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
+        return;
+    }
+    ALOGE("8 bit integer source does not match allocation type %i", dt);
+}
+
+void Allocation::validateIsFloat32() {
+    RsDataType dt = mType->getElement()->getDataType();
+    if (dt == RS_TYPE_FLOAT_32) {
+        return;
+    }
+    ALOGE("32 bit float source does not match allocation type %i", dt);
+}
+
+void Allocation::validateIsObject() {
+    RsDataType dt = mType->getElement()->getDataType();
+    if ((dt == RS_TYPE_ELEMENT) ||
+        (dt == RS_TYPE_TYPE) ||
+        (dt == RS_TYPE_ALLOCATION) ||
+        (dt == RS_TYPE_SAMPLER) ||
+        (dt == RS_TYPE_SCRIPT) ||
+        (dt == RS_TYPE_MESH) ||
+        (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
+        (dt == RS_TYPE_PROGRAM_VERTEX) ||
+        (dt == RS_TYPE_PROGRAM_RASTER) ||
+        (dt == RS_TYPE_PROGRAM_STORE)) {
+        return;
+    }
+    ALOGE("Object source does not match allocation type %i", dt);
+}
+
+void Allocation::updateFromNative() {
+    BaseObj::updateFromNative();
+
+    const void *typeID = rsaAllocationGetType(mRS->mContext, getID());
+    if(typeID != NULL) {
+        const Type *old = mType;
+        Type *t = new Type((void *)typeID, mRS);
+        t->updateFromNative();
+        updateCacheInfo(t);
+        mType = t;
+        delete old;
+    }
+}
+
+void Allocation::syncAll(RsAllocationUsageType srcLocation) {
+    switch (srcLocation) {
+    case RS_ALLOCATION_USAGE_SCRIPT:
+    case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
+    case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
+    case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
+        break;
+    default:
+        ALOGE("Source must be exactly one usage type.");
+    }
+    rsAllocationSyncAll(mRS->mContext, getIDSafe(), srcLocation);
+}
+
+void Allocation::ioSendOutput() {
+    if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
+        ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
+    }
+    rsAllocationIoSend(mRS->mContext, getID());
+}
+
+void Allocation::ioGetInput() {
+    if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
+        ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
+    }
+    rsAllocationIoReceive(mRS->mContext, getID());
+}
+
+/*
+void copyFrom(BaseObj[] d) {
+    mRS.validate();
+    validateIsObject();
+    if (d.length != mCurrentCount) {
+        ALOGE("Array size mismatch, allocation sizeX = " +
+                                             mCurrentCount + ", array length = " + d.length);
+    }
+    int i[] = new int[d.length];
+    for (int ct=0; ct < d.length; ct++) {
+        i[ct] = d[ct].getID();
+    }
+    copy1DRangeFromUnchecked(0, mCurrentCount, i);
+}
+*/
+
+
+/*
+void Allocation::setFromFieldPacker(int xoff, FieldPacker fp) {
+    mRS.validate();
+    int eSize = mType.mElement.getSizeBytes();
+    final byte[] data = fp.getData();
+
+    int count = data.length / eSize;
+    if ((eSize * count) != data.length) {
+        ALOGE("Field packer length " + data.length +
+                                           " not divisible by element size " + eSize + ".");
+    }
+    copy1DRangeFromUnchecked(xoff, count, data);
+}
+
+void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
+    mRS.validate();
+    if (component_number >= mType.mElement.mElements.length) {
+        ALOGE("Component_number " + component_number + " out of range.");
+    }
+    if(xoff < 0) {
+        ALOGE("Offset must be >= 0.");
+    }
+
+    final byte[] data = fp.getData();
+    int eSize = mType.mElement.mElements[component_number].getSizeBytes();
+    eSize *= mType.mElement.mArraySizes[component_number];
+
+    if (data.length != eSize) {
+        ALOGE("Field packer sizelength " + data.length +
+                                           " does not match component size " + eSize + ".");
+    }
+
+    mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
+                                 component_number, data, data.length);
+}
+*/
+
+void Allocation::generateMipmaps() {
+    rsAllocationGenerateMipmaps(mRS->mContext, getID());
+}
+
+void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data, size_t dataLen) {
+    if(count < 1) {
+        ALOGE("Count must be >= 1.");
+        return;
+    }
+    if((off + count) > mCurrentCount) {
+        ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
+        return;
+    }
+    if((count * mType->getElement()->getSizeBytes()) > dataLen) {
+        ALOGE("Array too small for allocation type.");
+        return;
+    }
+
+    rsAllocation1DData(mRS->mContext, getIDSafe(), off, mSelectedLOD, count, data, dataLen);
+}
+
+void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) {
+    validateIsInt32();
+    copy1DRangeFromUnchecked(off, count, d, dataLen);
+}
+
+void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) {
+    validateIsInt16();
+    copy1DRangeFromUnchecked(off, count, d, dataLen);
+}
+
+void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) {
+    validateIsInt8();
+    copy1DRangeFromUnchecked(off, count, d, dataLen);
+}
+
+void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) {
+    validateIsFloat32();
+    copy1DRangeFromUnchecked(off, count, d, dataLen);
+}
+
+void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data, uint32_t dataOff) {
+    rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), off, 0,
+                            mSelectedLOD, mSelectedFace,
+                            count, 1, data->getIDSafe(), dataOff, 0,
+                            data->mSelectedLOD, data->mSelectedFace);
+}
+
+void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
+    if (mAdaptedAllocation != NULL) {
+
+    } else {
+        if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
+            ALOGE("Updated region larger than allocation.");
+        }
+    }
+}
+
+void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                                 const int8_t *data, size_t dataLen) {
+    validate2DRange(xoff, yoff, w, h);
+    rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
+                       w, h, data, dataLen);
+}
+
+void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                                 const int16_t *data, size_t dataLen) {
+    validate2DRange(xoff, yoff, w, h);
+    rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
+                       w, h, data, dataLen);
+}
+
+void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                                 const int32_t *data, size_t dataLen) {
+    validate2DRange(xoff, yoff, w, h);
+    rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
+                       w, h, data, dataLen);
+}
+
+void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                                 const float *data, size_t dataLen) {
+    validate2DRange(xoff, yoff, w, h);
+    rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
+                       w, h, data, dataLen);
+}
+
+void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                                 const Allocation *data, size_t dataLen,
+                                 uint32_t dataXoff, uint32_t dataYoff) {
+    validate2DRange(xoff, yoff, w, h);
+    rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), xoff, yoff,
+                            mSelectedLOD, mSelectedFace,
+                            w, h, data->getIDSafe(), dataXoff, dataYoff,
+                            data->mSelectedLOD, data->mSelectedFace);
+}
+
+/*
+void copyTo(byte[] d) {
+    validateIsInt8();
+    mRS.validate();
+    mRS.nAllocationRead(getID(), d);
+}
+
+void copyTo(short[] d) {
+    validateIsInt16();
+    mRS.validate();
+    mRS.nAllocationRead(getID(), d);
+}
+
+void copyTo(int[] d) {
+    validateIsInt32();
+    mRS.validate();
+    mRS.nAllocationRead(getID(), d);
+}
+
+void copyTo(float[] d) {
+    validateIsFloat32();
+    mRS.validate();
+    mRS.nAllocationRead(getID(), d);
+}
+
+void resize(int dimX) {
+    if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
+        throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
+    }
+    mRS.nAllocationResize1D(getID(), dimX);
+    mRS.finish();  // Necessary because resize is fifoed and update is async.
+
+    int typeID = mRS.nAllocationGetType(getID());
+    mType = new Type(typeID, mRS);
+    mType.updateFromNative();
+    updateCacheInfo(mType);
+}
+
+void resize(int dimX, int dimY) {
+    if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
+        throw new RSInvalidStateException(
+            "Resize only support for 2D allocations at this time.");
+    }
+    if (mType.getY() == 0) {
+        throw new RSInvalidStateException(
+            "Resize only support for 2D allocations at this time.");
+    }
+    mRS.nAllocationResize2D(getID(), dimX, dimY);
+    mRS.finish();  // Necessary because resize is fifoed and update is async.
+
+    int typeID = mRS.nAllocationGetType(getID());
+    mType = new Type(typeID, mRS);
+    mType.updateFromNative();
+    updateCacheInfo(mType);
+}
+*/
+
+
+Allocation *Allocation::createTyped(RenderScript *rs, const Type *type,
+                        RsAllocationMipmapControl mips, uint32_t usage) {
+    void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, 0);
+    if (id == 0) {
+        ALOGE("Allocation creation failed.");
+        return NULL;
+    }
+    return new Allocation(id, rs, type, usage);
+}
+
+Allocation *Allocation::createTyped(RenderScript *rs, const Type *type,
+                                    RsAllocationMipmapControl mips, uint32_t usage, void *pointer) {
+    void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, (uint32_t)pointer);
+    if (id == 0) {
+        ALOGE("Allocation creation failed.");
+    }
+    return new Allocation(id, rs, type, usage);
+}
+
+Allocation *Allocation::createTyped(RenderScript *rs, const Type *type, uint32_t usage) {
+    return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
+}
+
+Allocation *Allocation::createSized(RenderScript *rs, const Element *e, size_t count, uint32_t usage) {
+    Type::Builder b(rs, e);
+    b.setX(count);
+    const Type *t = b.create();
+
+    void *id = rsAllocationCreateTyped(rs->mContext, t->getID(), RS_ALLOCATION_MIPMAP_NONE, usage, 0);
+    if (id == 0) {
+        ALOGE("Allocation creation failed.");
+    }
+    return new Allocation(id, rs, t, usage);
+}
+
+
+/*
+SurfaceTexture getSurfaceTexture() {
+    if ((mUsage & USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) == 0) {
+        throw new RSInvalidStateException("Allocation is not a surface texture.");
+    }
+
+    int id = mRS.nAllocationGetSurfaceTextureID(getID());
+    return new SurfaceTexture(id);
+
+}
+
+void setSurfaceTexture(SurfaceTexture sur) {
+    if ((mUsage & USAGE_IO_OUTPUT) == 0) {
+        throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
+    }
+
+    mRS.validate();
+    mRS.nAllocationSetSurfaceTexture(getID(), sur);
+}
+
+
+static Allocation createFromBitmapResource(RenderScript rs,
+                                                  Resources res,
+                                                  int id,
+                                                  MipmapControl mips,
+                                                  int usage) {
+
+    rs.validate();
+    Bitmap b = BitmapFactory.decodeResource(res, id);
+    Allocation alloc = createFromBitmap(rs, b, mips, usage);
+    b.recycle();
+    return alloc;
+}
+
+static Allocation createFromBitmapResource(RenderScript rs,
+                                                  Resources res,
+                                                  int id) {
+    return createFromBitmapResource(rs, res, id,
+                                    MipmapControl.MIPMAP_NONE,
+                                    USAGE_GRAPHICS_TEXTURE);
+}
+
+static Allocation createFromString(RenderScript rs,
+                                          String str,
+                                          int usage) {
+    rs.validate();
+    byte[] allocArray = NULL;
+    try {
+        allocArray = str.getBytes("UTF-8");
+        Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
+        alloc.copyFrom(allocArray);
+        return alloc;
+    }
+    catch (Exception e) {
+        throw new RSRuntimeException("Could not convert string to utf-8.");
+    }
+}
+*/
+
diff --git a/libs/rs/Allocation.h b/libs/rs/Allocation.h
new file mode 100644
index 0000000..c9e00a4
--- /dev/null
+++ b/libs/rs/Allocation.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_ALLOCATION_H__
+#define __ANDROID_ALLOCATION_H__
+
+#include <pthread.h>
+#include <rs.h>
+
+#include "RenderScript.h"
+#include "Type.h"
+#include "Element.h"
+
+class Allocation : public BaseObj {
+protected:
+    const Type *mType;
+    uint32_t mUsage;
+    Allocation *mAdaptedAllocation;
+
+    bool mConstrainedLOD;
+    bool mConstrainedFace;
+    bool mConstrainedY;
+    bool mConstrainedZ;
+    bool mReadAllowed;
+    bool mWriteAllowed;
+    uint32_t mSelectedY;
+    uint32_t mSelectedZ;
+    uint32_t mSelectedLOD;
+    RsAllocationCubemapFace mSelectedFace;
+
+    uint32_t mCurrentDimX;
+    uint32_t mCurrentDimY;
+    uint32_t mCurrentDimZ;
+    uint32_t mCurrentCount;
+
+
+    void * getIDSafe() const;
+    void updateCacheInfo(const Type *t);
+
+    Allocation(void *id, RenderScript *rs, const Type *t, uint32_t usage);
+
+    void validateIsInt32();
+    void validateIsInt16();
+    void validateIsInt8();
+    void validateIsFloat32();
+    void validateIsObject();
+
+    virtual void updateFromNative();
+
+    void validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h);
+
+public:
+    const Type * getType() {
+        return mType;
+    }
+
+    void syncAll(RsAllocationUsageType srcLocation);
+    void ioSendOutput();
+    void ioGetInput();
+
+    //void copyFrom(BaseObj[] d);
+    //void copyFromUnchecked(int[] d);
+    //void copyFromUnchecked(short[] d);
+    //void copyFromUnchecked(byte[] d);
+    //void copyFromUnchecked(float[] d);
+    //void copyFrom(int[] d);
+    //void copyFrom(short[] d);
+    //void copyFrom(byte[] d);
+    //void copyFrom(float[] d);
+    //void setFromFieldPacker(int xoff, FieldPacker fp);
+    //void setFromFieldPacker(int xoff, int component_number, FieldPacker fp);
+    void generateMipmaps();
+    void copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data, size_t dataLen);
+    void copy1DRangeFrom(uint32_t off, size_t count, const int32_t* d, size_t dataLen);
+    void copy1DRangeFrom(uint32_t off, size_t count, const int16_t* d, size_t dataLen);
+    void copy1DRangeFrom(uint32_t off, size_t count, const int8_t* d, size_t dataLen);
+    void copy1DRangeFrom(uint32_t off, size_t count, const float* d, size_t dataLen);
+    void copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data, uint32_t dataOff);
+
+    void copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                         const int32_t *data, size_t dataLen);
+    void copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                         const int16_t *data, size_t dataLen);
+    void copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                         const int8_t *data, size_t dataLen);
+    void copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                         const float *data, size_t dataLen);
+    void copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
+                         const Allocation *data, size_t dataLen,
+                         uint32_t dataXoff, uint32_t dataYoff);
+
+    //void copyTo(byte[] d);
+    //void copyTo(short[] d);
+    //void copyTo(int[] d);
+    //void copyTo(float[] d);
+    void resize(int dimX);
+    void resize(int dimX, int dimY);
+
+    static Allocation *createTyped(RenderScript *rs, const Type *type,
+                                   RsAllocationMipmapControl mips, uint32_t usage);
+    static Allocation *createTyped(RenderScript *rs, const Type *type,
+                                   RsAllocationMipmapControl mips, uint32_t usage, void * pointer);
+
+    static Allocation *createTyped(RenderScript *rs, const Type *type,
+                                   uint32_t usage = RS_ALLOCATION_USAGE_SCRIPT);
+    static Allocation *createSized(RenderScript *rs, const Element *e, size_t count,
+                                   uint32_t usage = RS_ALLOCATION_USAGE_SCRIPT);
+    //SurfaceTexture *getSurfaceTexture();
+    //void setSurfaceTexture(SurfaceTexture *sur);
+
+};
+
+#endif
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 9c5d06b..45ed453 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -127,7 +127,14 @@
 	driver/rsdSampler.cpp \
 	driver/rsdShader.cpp \
 	driver/rsdShaderCache.cpp \
-	driver/rsdVertexArray.cpp
+	driver/rsdVertexArray.cpp \
+	RenderScript.cpp \
+	BaseObj.cpp \
+	Element.cpp \
+	Type.cpp \
+	Allocation.cpp \
+	Script.cpp \
+	ScriptC.cpp
 
 LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc libbcinfo libgui
 
diff --git a/libs/rs/BaseObj.cpp b/libs/rs/BaseObj.cpp
new file mode 100644
index 0000000..66e6fac
--- /dev/null
+++ b/libs/rs/BaseObj.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <rs.h>
+
+#include "RenderScript.h"
+#include "BaseObj.h"
+
+void * BaseObj::getID() const {
+    if (mID == NULL) {
+        ALOGE("Internal error: Object id 0.");
+    }
+    return mID;
+}
+
+void * BaseObj::getObjID(const BaseObj *o) {
+    return o == NULL ? NULL : o->getID();
+}
+
+
+BaseObj::BaseObj(void *id, RenderScript *rs) {
+    mRS = rs;
+    mID = id;
+}
+
+void BaseObj::checkValid() {
+    if (mID == 0) {
+        ALOGE("Invalid object.");
+    }
+}
+
+BaseObj::~BaseObj() {
+    rsObjDestroy(mRS->mContext, mID);
+    mRS = NULL;
+    mID = NULL;
+}
+
+void BaseObj::updateFromNative() {
+    const char *name = NULL;
+    rsaGetName(mRS, mID, &name);
+    mName = name;
+}
+
+bool BaseObj::equals(const BaseObj *obj) {
+    // Early-out check to see if both BaseObjs are actually the same
+    if (this == obj)
+        return true;
+    return mID == obj->mID;
+}
+
+
+
diff --git a/libs/rs/BaseObj.h b/libs/rs/BaseObj.h
new file mode 100644
index 0000000..79761b1
--- /dev/null
+++ b/libs/rs/BaseObj.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_BASE_OBJ_H__
+#define __ANDROID_BASE_OBJ_H__
+
+
+#include <pthread.h>
+#include <rs.h>
+
+#include "RenderScript.h"
+
+class BaseObj {
+protected:
+    friend class Element;
+    friend class Type;
+    friend class Allocation;
+    friend class Script;
+    friend class ScriptC;
+
+    void *mID;
+    RenderScript *mRS;
+    android::String8 mName;
+
+    void * getID() const;
+
+    BaseObj(void *id, RenderScript *rs);
+    void checkValid();
+
+    static void * getObjID(const BaseObj *o);
+
+public:
+
+    virtual ~BaseObj();
+    virtual void updateFromNative();
+    virtual bool equals(const BaseObj *obj);
+};
+
+#endif
diff --git a/libs/rs/Element.cpp b/libs/rs/Element.cpp
new file mode 100644
index 0000000..d193892
--- /dev/null
+++ b/libs/rs/Element.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "RenderScript.h"
+#include "Element.h"
+
+
+const Element * Element::getSubElement(uint32_t index) {
+    if (!mVisibleElementMap.size()) {
+        mRS->throwError("Element contains no sub-elements");
+    }
+    if (index >= mVisibleElementMap.size()) {
+        mRS->throwError("Illegal sub-element index");
+    }
+    return mElements[mVisibleElementMap[index]];
+}
+
+const char * Element::getSubElementName(uint32_t index) {
+    if (!mVisibleElementMap.size()) {
+        mRS->throwError("Element contains no sub-elements");
+    }
+    if (index >= mVisibleElementMap.size()) {
+        mRS->throwError("Illegal sub-element index");
+    }
+    return mElementNames[mVisibleElementMap[index]];
+}
+
+size_t Element::getSubElementArraySize(uint32_t index) {
+    if (!mVisibleElementMap.size()) {
+        mRS->throwError("Element contains no sub-elements");
+    }
+    if (index >= mVisibleElementMap.size()) {
+        mRS->throwError("Illegal sub-element index");
+    }
+    return mArraySizes[mVisibleElementMap[index]];
+}
+
+uint32_t Element::getSubElementOffsetBytes(uint32_t index) {
+    if (mVisibleElementMap.size()) {
+        mRS->throwError("Element contains no sub-elements");
+    }
+    if (index >= mVisibleElementMap.size()) {
+        mRS->throwError("Illegal sub-element index");
+    }
+    return mOffsetInBytes[mVisibleElementMap[index]];
+}
+
+
+#define CREATE_USER(N, T) const Element * Element::N(RenderScript *rs) { \
+    return createUser(rs, RS_TYPE_##T); \
+}
+CREATE_USER(BOOLEAN, BOOLEAN);
+CREATE_USER(U8, UNSIGNED_8);
+CREATE_USER(I8, SIGNED_8);
+CREATE_USER(U16, UNSIGNED_16);
+CREATE_USER(I16, SIGNED_16);
+CREATE_USER(U32, UNSIGNED_32);
+CREATE_USER(I32, SIGNED_32);
+CREATE_USER(U64, UNSIGNED_64);
+CREATE_USER(I64, SIGNED_64);
+CREATE_USER(F32, FLOAT_32);
+CREATE_USER(F64, FLOAT_64);
+CREATE_USER(ELEMENT, ELEMENT);
+CREATE_USER(TYPE, TYPE);
+CREATE_USER(ALLOCATION, ALLOCATION);
+CREATE_USER(SAMPLER, SAMPLER);
+CREATE_USER(SCRIPT, SCRIPT);
+CREATE_USER(MESH, MESH);
+CREATE_USER(PROGRAM_FRAGMENT, PROGRAM_FRAGMENT);
+CREATE_USER(PROGRAM_VERTEX, PROGRAM_VERTEX);
+CREATE_USER(PROGRAM_RASTER, PROGRAM_RASTER);
+CREATE_USER(PROGRAM_STORE, PROGRAM_STORE);
+CREATE_USER(MATRIX_4X4, MATRIX_4X4);
+CREATE_USER(MATRIX_3X3, MATRIX_3X3);
+CREATE_USER(MATRIX_2X2, MATRIX_2X2);
+
+#define CREATE_PIXEL(N, T, K) const Element * Element::N(RenderScript *rs) { \
+    return createPixel(rs, RS_TYPE_##T, RS_KIND_##K); \
+}
+CREATE_PIXEL(A_8, UNSIGNED_8, PIXEL_A);
+CREATE_PIXEL(RGB_565, UNSIGNED_5_6_5, PIXEL_RGB);
+CREATE_PIXEL(RGB_888, UNSIGNED_8, PIXEL_RGB);
+CREATE_PIXEL(RGBA_4444, UNSIGNED_4_4_4_4, PIXEL_RGBA);
+CREATE_PIXEL(RGBA_8888, UNSIGNED_8, PIXEL_RGBA);
+
+#define CREATE_VECTOR(N, T) const Element * Element::N##_2(RenderScript *rs) { \
+    return createVector(rs, RS_TYPE_##T, 2); \
+} \
+const Element * Element::N##_3(RenderScript *rs) { \
+    return createVector(rs, RS_TYPE_##T, 3); \
+} \
+const Element * Element::N##_4(RenderScript *rs) { \
+    return createVector(rs, RS_TYPE_##T, 4); \
+}
+CREATE_VECTOR(U8, UNSIGNED_8);
+CREATE_VECTOR(I8, SIGNED_8);
+CREATE_VECTOR(U16, UNSIGNED_16);
+CREATE_VECTOR(I16, SIGNED_16);
+CREATE_VECTOR(U32, UNSIGNED_32);
+CREATE_VECTOR(I32, SIGNED_32);
+CREATE_VECTOR(U64, UNSIGNED_64);
+CREATE_VECTOR(I64, SIGNED_64);
+CREATE_VECTOR(F32, FLOAT_32);
+CREATE_VECTOR(F64, FLOAT_64);
+
+
+void Element::updateVisibleSubElements() {
+    if (!mElements.size()) {
+        return;
+    }
+    mVisibleElementMap.clear();
+
+    int noPaddingFieldCount = 0;
+    size_t fieldCount = mElementNames.size();
+    // Find out how many elements are not padding
+    for (size_t ct = 0; ct < fieldCount; ct ++) {
+        if (mElementNames[ct].string()[0] != '#') {
+            noPaddingFieldCount ++;
+        }
+    }
+
+    // Make a map that points us at non-padding elements
+    for (size_t ct = 0; ct < fieldCount; ct ++) {
+        if (mElementNames[ct].string()[0] != '#') {
+            mVisibleElementMap.push((uint32_t)ct);
+        }
+    }
+}
+
+Element::Element(void *id, RenderScript *rs,
+                 android::Vector<const Element *> &elements,
+                 android::Vector<android::String8> &elementNames,
+                 android::Vector<uint32_t> &arraySizes) : BaseObj(id, rs) {
+    mSizeBytes = 0;
+    mVectorSize = 1;
+    mElements = elements;
+    mArraySizes = arraySizes;
+    mElementNames = elementNames;
+
+    mType = RS_TYPE_NONE;
+    mKind = RS_KIND_USER;
+
+    for (size_t ct = 0; ct < mElements.size(); ct++ ) {
+        mOffsetInBytes.push(mSizeBytes);
+        mSizeBytes += mElements[ct]->mSizeBytes * mArraySizes[ct];
+    }
+    updateVisibleSubElements();
+}
+
+
+static uint32_t GetSizeInBytesForType(RsDataType dt) {
+    switch(dt) {
+    case RS_TYPE_NONE:
+        return 0;
+    case RS_TYPE_SIGNED_8:
+    case RS_TYPE_UNSIGNED_8:
+    case RS_TYPE_BOOLEAN:
+        return 1;
+
+    case RS_TYPE_FLOAT_16:
+    case RS_TYPE_SIGNED_16:
+    case RS_TYPE_UNSIGNED_16:
+    case RS_TYPE_UNSIGNED_5_6_5:
+    case RS_TYPE_UNSIGNED_5_5_5_1:
+    case RS_TYPE_UNSIGNED_4_4_4_4:
+        return 2;
+
+    case RS_TYPE_FLOAT_32:
+    case RS_TYPE_SIGNED_32:
+    case RS_TYPE_UNSIGNED_32:
+        return 4;
+
+    case RS_TYPE_FLOAT_64:
+    case RS_TYPE_SIGNED_64:
+    case RS_TYPE_UNSIGNED_64:
+        return 8;
+
+    case RS_TYPE_MATRIX_4X4:
+        return 16 * 4;
+    case RS_TYPE_MATRIX_3X3:
+        return 9 * 4;
+    case RS_TYPE_MATRIX_2X2:
+        return 4 * 4;
+
+    case RS_TYPE_TYPE:
+    case RS_TYPE_ALLOCATION:
+    case RS_TYPE_SAMPLER:
+    case RS_TYPE_SCRIPT:
+    case RS_TYPE_MESH:
+    case RS_TYPE_PROGRAM_FRAGMENT:
+    case RS_TYPE_PROGRAM_VERTEX:
+    case RS_TYPE_PROGRAM_RASTER:
+    case RS_TYPE_PROGRAM_STORE:
+        return 4;
+
+    default:
+        break;
+    }
+
+    ALOGE("Missing type %i", dt);
+    return 0;
+}
+
+Element::Element(void *id, RenderScript *rs,
+                 RsDataType dt, RsDataKind dk, bool norm, uint32_t size) :
+    BaseObj(id, rs)
+{
+    uint32_t tsize = GetSizeInBytesForType(dt);
+    if ((dt != RS_TYPE_UNSIGNED_5_6_5) &&
+        (dt != RS_TYPE_UNSIGNED_4_4_4_4) &&
+        (dt != RS_TYPE_UNSIGNED_5_5_5_1)) {
+        if (size == 3) {
+            mSizeBytes = tsize * 4;
+        } else {
+            mSizeBytes = tsize * size;
+        }
+    } else {
+        mSizeBytes = tsize;
+    }
+    mType = dt;
+    mKind = dk;
+    mNormalized = norm;
+    mVectorSize = size;
+}
+
+Element::~Element() {
+}
+
+   /*
+    Element(int id, RenderScript rs) {
+        super(id, rs);
+    }
+    */
+
+void Element::updateFromNative() {
+    BaseObj::updateFromNative();
+/*
+    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
+    int[] dataBuffer = new int[5];
+    mRS.nElementGetNativeData(getID(), dataBuffer);
+
+    mNormalized = dataBuffer[2] == 1 ? true : false;
+    mVectorSize = dataBuffer[3];
+    mSize = 0;
+    for (DataType dt: DataType.values()) {
+        if(dt.mID == dataBuffer[0]){
+            mType = dt;
+            mSize = mType.mSize * mVectorSize;
+        }
+    }
+    for (DataKind dk: DataKind.values()) {
+        if(dk.mID == dataBuffer[1]){
+            mKind = dk;
+        }
+    }
+
+    int numSubElements = dataBuffer[4];
+    if(numSubElements > 0) {
+        mElements = new Element[numSubElements];
+        mElementNames = new String[numSubElements];
+        mArraySizes = new int[numSubElements];
+        mOffsetInBytes = new int[numSubElements];
+
+        int[] subElementIds = new int[numSubElements];
+        mRS.nElementGetSubElements(getID(), subElementIds, mElementNames, mArraySizes);
+        for(int i = 0; i < numSubElements; i ++) {
+            mElements[i] = new Element(subElementIds[i], mRS);
+            mElements[i].updateFromNative();
+            mOffsetInBytes[i] = mSize;
+            mSize += mElements[i].mSize * mArraySizes[i];
+        }
+    }
+    */
+    updateVisibleSubElements();
+}
+
+const Element * Element::createUser(RenderScript *rs, RsDataType dt) {
+    void * id = rsElementCreate(rs->mContext, dt, RS_KIND_USER, false, 1);
+    return new Element(id, rs, dt, RS_KIND_USER, false, 1);
+}
+
+const Element * Element::createVector(RenderScript *rs, RsDataType dt, uint32_t size) {
+    if (size < 2 || size > 4) {
+        rs->throwError("Vector size out of range 2-4.");
+    }
+    void *id = rsElementCreate(rs->mContext, dt, RS_KIND_USER, false, size);
+    return new Element(id, rs, dt, RS_KIND_USER, false, size);
+}
+
+const Element * Element::createPixel(RenderScript *rs, RsDataType dt, RsDataKind dk) {
+    if (!(dk == RS_KIND_PIXEL_L ||
+          dk == RS_KIND_PIXEL_A ||
+          dk == RS_KIND_PIXEL_LA ||
+          dk == RS_KIND_PIXEL_RGB ||
+          dk == RS_KIND_PIXEL_RGBA ||
+          dk == RS_KIND_PIXEL_DEPTH)) {
+        rs->throwError("Unsupported DataKind");
+    }
+    if (!(dt == RS_TYPE_UNSIGNED_8 ||
+          dt == RS_TYPE_UNSIGNED_16 ||
+          dt == RS_TYPE_UNSIGNED_5_6_5 ||
+          dt == RS_TYPE_UNSIGNED_4_4_4_4 ||
+          dt == RS_TYPE_UNSIGNED_5_5_5_1)) {
+        rs->throwError("Unsupported DataType");
+    }
+    if (dt == RS_TYPE_UNSIGNED_5_6_5 && dk != RS_KIND_PIXEL_RGB) {
+        rs->throwError("Bad kind and type combo");
+    }
+    if (dt == RS_TYPE_UNSIGNED_5_5_5_1 && dk != RS_KIND_PIXEL_RGBA) {
+        rs->throwError("Bad kind and type combo");
+    }
+    if (dt == RS_TYPE_UNSIGNED_4_4_4_4 && dk != RS_KIND_PIXEL_RGBA) {
+        rs->throwError("Bad kind and type combo");
+    }
+    if (dt == RS_TYPE_UNSIGNED_16 && dk != RS_KIND_PIXEL_DEPTH) {
+        rs->throwError("Bad kind and type combo");
+    }
+
+    int size = 1;
+    switch (dk) {
+    case RS_KIND_PIXEL_LA:
+        size = 2;
+        break;
+    case RS_KIND_PIXEL_RGB:
+        size = 3;
+        break;
+    case RS_KIND_PIXEL_RGBA:
+        size = 4;
+        break;
+    case RS_KIND_PIXEL_DEPTH:
+        size = 2;
+        break;
+    default:
+        break;
+    }
+
+    void * id = rsElementCreate(rs->mContext, dt, dk, true, size);
+    return new Element(id, rs, dt, dk, true, size);
+}
+
+bool Element::isCompatible(const Element *e) {
+    // Try strict BaseObj equality to start with.
+    if (this == e) {
+        return true;
+    }
+
+    // Ignore mKind because it is allowed to be different (user vs. pixel).
+    // We also ignore mNormalized because it can be different. The mType
+    // field must be non-null since we require name equivalence for
+    // user-created Elements.
+    return ((mSizeBytes == e->mSizeBytes) &&
+            (mType != NULL) &&
+            (mType == e->mType) &&
+            (mVectorSize == e->mVectorSize));
+}
+
+Element::Builder::Builder(RenderScript *rs) {
+    mRS = rs;
+    mSkipPadding = false;
+}
+
+void Element::Builder::add(const Element *e, android::String8 &name, uint32_t arraySize) {
+    // Skip padding fields after a vector 3 type.
+    if (mSkipPadding) {
+        const char *s1 = "#padding_";
+        const char *s2 = name;
+        size_t len = strlen(s1);
+        if (strlen(s2) >= len) {
+            if (!memcmp(s1, s2, len)) {
+                mSkipPadding = false;
+                return;
+            }
+        }
+    }
+
+    if (e->mVectorSize == 3) {
+        mSkipPadding = true;
+    } else {
+        mSkipPadding = false;
+    }
+
+    mElements.add(e);
+    mElementNames.add(name);
+    mArraySizes.add(arraySize);
+}
+
+const Element * Element::Builder::create() {
+    size_t fieldCount = mElements.size();
+    const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
+    size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
+
+    for (size_t ct = 0; ct < fieldCount; ct++) {
+        nameArray[ct] = mElementNames[ct].string();
+        sizeArray[ct] = mElementNames[ct].length();
+    }
+
+    void *id = rsElementCreate2(mRS->mContext,
+                                (RsElement *)mElements.array(), fieldCount,
+                                nameArray, fieldCount * sizeof(size_t),  sizeArray,
+                                (const uint32_t *)mArraySizes.array(), fieldCount);
+
+
+    free(nameArray);
+    free(sizeArray);
+
+    Element *e = new Element(id, mRS, mElements, mElementNames, mArraySizes);
+    return e;
+}
+
diff --git a/libs/rs/Element.h b/libs/rs/Element.h
new file mode 100644
index 0000000..a579dc3
--- /dev/null
+++ b/libs/rs/Element.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_ELEMENT_H__
+#define __ANDROID_ELEMENT_H__
+
+#include <rs.h>
+#include "RenderScript.h"
+#include "BaseObj.h"
+
+class Element : public BaseObj {
+public:
+    /**
+     * Return if a element is too complex for use as a data source for a Mesh or
+     * a Program.
+     *
+     * @return boolean
+     */
+    bool isComplex();
+
+    /**
+    * @hide
+    * @return number of sub-elements in this element
+    */
+    size_t getSubElementCount() {
+        return mVisibleElementMap.size();
+    }
+
+    /**
+    * @hide
+    * @param index index of the sub-element to return
+    * @return sub-element in this element at given index
+    */
+    const Element * getSubElement(uint32_t index);
+
+    /**
+    * @hide
+    * @param index index of the sub-element
+    * @return sub-element in this element at given index
+    */
+    const char * getSubElementName(uint32_t index);
+
+    /**
+    * @hide
+    * @param index index of the sub-element
+    * @return array size of sub-element in this element at given index
+    */
+    size_t getSubElementArraySize(uint32_t index);
+
+    /**
+    * @hide
+    * @param index index of the sub-element
+    * @return offset in bytes of sub-element in this element at given index
+    */
+    uint32_t getSubElementOffsetBytes(uint32_t index);
+
+    /**
+    * @hide
+    * @return element data type
+    */
+    RsDataType getDataType() const {
+        return mType;
+    }
+
+    /**
+    * @hide
+    * @return element data kind
+    */
+    RsDataKind getDataKind() const {
+        return mKind;
+    }
+
+    size_t getSizeBytes() const {
+        return mSizeBytes;
+    }
+
+
+    static const Element * BOOLEAN(RenderScript *rs);
+    static const Element * U8(RenderScript *rs);
+    static const Element * I8(RenderScript *rs);
+    static const Element * U16(RenderScript *rs);
+    static const Element * I16(RenderScript *rs);
+    static const Element * U32(RenderScript *rs);
+    static const Element * I32(RenderScript *rs);
+    static const Element * U64(RenderScript *rs);
+    static const Element * I64(RenderScript *rs);
+    static const Element * F32(RenderScript *rs);
+    static const Element * F64(RenderScript *rs);
+    static const Element * ELEMENT(RenderScript *rs);
+    static const Element * TYPE(RenderScript *rs);
+    static const Element * ALLOCATION(RenderScript *rs);
+    static const Element * SAMPLER(RenderScript *rs);
+    static const Element * SCRIPT(RenderScript *rs);
+    static const Element * MESH(RenderScript *rs);
+    static const Element * PROGRAM_FRAGMENT(RenderScript *rs);
+    static const Element * PROGRAM_VERTEX(RenderScript *rs);
+    static const Element * PROGRAM_RASTER(RenderScript *rs);
+    static const Element * PROGRAM_STORE(RenderScript *rs);
+
+    static const Element * A_8(RenderScript *rs);
+    static const Element * RGB_565(RenderScript *rs);
+    static const Element * RGB_888(RenderScript *rs);
+    static const Element * RGBA_5551(RenderScript *rs);
+    static const Element * RGBA_4444(RenderScript *rs);
+    static const Element * RGBA_8888(RenderScript *rs);
+
+    static const Element * F32_2(RenderScript *rs);
+    static const Element * F32_3(RenderScript *rs);
+    static const Element * F32_4(RenderScript *rs);
+    static const Element * F64_2(RenderScript *rs);
+    static const Element * F64_3(RenderScript *rs);
+    static const Element * F64_4(RenderScript *rs);
+    static const Element * U8_2(RenderScript *rs);
+    static const Element * U8_3(RenderScript *rs);
+    static const Element * U8_4(RenderScript *rs);
+    static const Element * I8_2(RenderScript *rs);
+    static const Element * I8_3(RenderScript *rs);
+    static const Element * I8_4(RenderScript *rs);
+    static const Element * U16_2(RenderScript *rs);
+    static const Element * U16_3(RenderScript *rs);
+    static const Element * U16_4(RenderScript *rs);
+    static const Element * I16_2(RenderScript *rs);
+    static const Element * I16_3(RenderScript *rs);
+    static const Element * I16_4(RenderScript *rs);
+    static const Element * U32_2(RenderScript *rs);
+    static const Element * U32_3(RenderScript *rs);
+    static const Element * U32_4(RenderScript *rs);
+    static const Element * I32_2(RenderScript *rs);
+    static const Element * I32_3(RenderScript *rs);
+    static const Element * I32_4(RenderScript *rs);
+    static const Element * U64_2(RenderScript *rs);
+    static const Element * U64_3(RenderScript *rs);
+    static const Element * U64_4(RenderScript *rs);
+    static const Element * I64_2(RenderScript *rs);
+    static const Element * I64_3(RenderScript *rs);
+    static const Element * I64_4(RenderScript *rs);
+    static const Element * MATRIX_4X4(RenderScript *rs);
+    static const Element * MATRIX_3X3(RenderScript *rs);
+    static const Element * MATRIX_2X2(RenderScript *rs);
+
+    Element(void *id, RenderScript *rs,
+            android::Vector<const Element *> &elements,
+            android::Vector<android::String8> &elementNames,
+            android::Vector<uint32_t> &arraySizes);
+    Element(void *id, RenderScript *rs, RsDataType dt, RsDataKind dk, bool norm, uint32_t size);
+    Element(RenderScript *rs);
+    virtual ~Element();
+
+    void updateFromNative();
+    static const Element * createUser(RenderScript *rs, RsDataType dt);
+    static const Element * createVector(RenderScript *rs, RsDataType dt, uint32_t size);
+    static const Element * createPixel(RenderScript *rs, RsDataType dt, RsDataKind dk);
+    bool isCompatible(const Element *e);
+
+    class Builder {
+    private:
+        RenderScript *mRS;
+        android::Vector<const Element *> mElements;
+        android::Vector<android::String8> mElementNames;
+        android::Vector<uint32_t> mArraySizes;
+        bool mSkipPadding;
+
+    public:
+        Builder(RenderScript *rs);
+        ~Builder();
+        void add(const Element *, android::String8 &name, uint32_t arraySize = 1);
+        const Element * create();
+    };
+
+private:
+    void updateVisibleSubElements();
+
+    android::Vector<const Element *> mElements;
+    android::Vector<android::String8> mElementNames;
+    android::Vector<uint32_t> mArraySizes;
+    android::Vector<uint32_t> mVisibleElementMap;
+    android::Vector<uint32_t> mOffsetInBytes;
+
+    RsDataType mType;
+    RsDataKind mKind;
+    bool mNormalized;
+    size_t mSizeBytes;
+    size_t mVectorSize;
+};
+
+#endif
diff --git a/libs/rs/RenderScript.cpp b/libs/rs/RenderScript.cpp
new file mode 100644
index 0000000..39f1024
--- /dev/null
+++ b/libs/rs/RenderScript.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "RenderScript.h"
+
+bool RenderScript::gInitialized = false;
+pthread_mutex_t RenderScript::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+
+RenderScript::RenderScript() {
+    mDev = NULL;
+    mContext = NULL;
+    mErrorFunc = NULL;
+    mMessageFunc = NULL;
+    mMessageRun = false;
+
+    memset(&mElements, 0, sizeof(mElements));
+}
+
+RenderScript::~RenderScript() {
+    mMessageRun = false;
+
+    rsContextDeinitToClient(mContext);
+
+    void *res = NULL;
+    int status = pthread_join(mMessageThreadId, &res);
+
+    rsContextDestroy(mContext);
+    mContext = NULL;
+    rsDeviceDestroy(mDev);
+    mDev = NULL;
+}
+
+bool RenderScript::init(int targetApi) {
+    mDev = rsDeviceCreate();
+    if (mDev == 0) {
+        ALOGE("Device creation failed");
+        return false;
+    }
+
+    mContext = rsContextCreate(mDev, 0, targetApi);
+    if (mContext == 0) {
+        ALOGE("Context creation failed");
+        return false;
+    }
+
+
+    pid_t mNativeMessageThreadId;
+
+    int status = pthread_create(&mMessageThreadId, NULL, threadProc, this);
+    if (status) {
+        ALOGE("Failed to start RenderScript message thread.");
+        return false;
+    }
+    // Wait for the message thread to be active.
+    while (!mMessageRun) {
+        usleep(1000);
+    }
+
+    return true;
+}
+
+void RenderScript::throwError(const char *err) const {
+    ALOGE("RS CPP error: %s", err);
+    int * v = NULL;
+    v[0] = 0;
+}
+
+
+void * RenderScript::threadProc(void *vrsc) {
+    RenderScript *rs = static_cast<RenderScript *>(vrsc);
+    size_t rbuf_size = 256;
+    void * rbuf = malloc(rbuf_size);
+
+    rsContextInitToClient(rs->mContext);
+    rs->mMessageRun = true;
+
+    while (rs->mMessageRun) {
+        size_t receiveLen = 0;
+        uint32_t usrID = 0;
+        uint32_t subID = 0;
+        RsMessageToClientType r = rsContextPeekMessage(rs->mContext,
+                                                       &receiveLen, sizeof(receiveLen),
+                                                       &usrID, sizeof(usrID));
+
+        if (receiveLen >= rbuf_size) {
+            rbuf_size = receiveLen + 32;
+            rbuf = realloc(rbuf, rbuf_size);
+        }
+        if (!rbuf) {
+            ALOGE("RenderScript::message handler realloc error %zu", rbuf_size);
+            // No clean way to recover now?
+        }
+        rsContextGetMessage(rs->mContext, rbuf, rbuf_size, &receiveLen, sizeof(receiveLen),
+                            &subID, sizeof(subID));
+
+        switch(r) {
+        case RS_MESSAGE_TO_CLIENT_ERROR:
+            ALOGE("RS Error %s", (const char *)rbuf);
+
+            if(rs->mMessageFunc != NULL) {
+                rs->mErrorFunc(usrID, (const char *)rbuf);
+            }
+            break;
+        case RS_MESSAGE_TO_CLIENT_EXCEPTION:
+            // teardown. But we want to avoid starving other threads during
+            // teardown by yielding until the next line in the destructor can
+            // execute to set mRun = false
+            usleep(1000);
+            break;
+        case RS_MESSAGE_TO_CLIENT_USER:
+            if(rs->mMessageFunc != NULL) {
+                rs->mMessageFunc(usrID, rbuf, receiveLen);
+            } else {
+                ALOGE("Received a message from the script with no message handler installed.");
+            }
+            break;
+
+        default:
+            ALOGE("RenderScript unknown message type %i", r);
+        }
+    }
+
+    if (rbuf) {
+        free(rbuf);
+    }
+    ALOGE("RenderScript Message thread exiting.");
+    return NULL;
+}
+
+void RenderScript::setErrorHandler(ErrorHandlerFunc_t func) {
+    mErrorFunc = func;
+}
+
+void RenderScript::setMessageHandler(MessageHandlerFunc_t func) {
+    mMessageFunc  = func;
+}
+
+void RenderScript::contextDump() {
+}
+
+void RenderScript::finish() {
+
+}
+
+
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
new file mode 100644
index 0000000..0eb6a6d
--- /dev/null
+++ b/libs/rs/RenderScript.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RENDERSCRIPT_H
+#define ANDROID_RENDERSCRIPT_H
+
+
+#include <pthread.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "rs.h"
+
+class Element;
+class Type;
+class Allocation;
+
+class RenderScript {
+    friend class BaseObj;
+    friend class Allocation;
+    friend class Element;
+    friend class Type;
+    friend class Script;
+    friend class ScriptC;
+
+public:
+    RenderScript();
+    virtual ~RenderScript();
+
+    typedef void (*ErrorHandlerFunc_t)(uint32_t errorNum, const char *errorText);
+    typedef void (*MessageHandlerFunc_t)(uint32_t msgNum, const void *msgData, size_t msgLen);
+
+
+    void setErrorHandler(ErrorHandlerFunc_t func);
+    ErrorHandlerFunc_t getErrorHandler() {return mErrorFunc;}
+
+    void setMessageHandler(MessageHandlerFunc_t func);
+    MessageHandlerFunc_t getMessageHandler() {return mMessageFunc;}
+
+    bool init(int targetApi);
+    void contextDump();
+    void finish();
+
+private:
+    static bool gInitialized;
+    static pthread_mutex_t gInitMutex;
+
+    pthread_t mMessageThreadId;
+    pid_t mNativeMessageThreadId;
+    bool mMessageRun;
+
+    RsDevice mDev;
+    RsContext mContext;
+
+    ErrorHandlerFunc_t mErrorFunc;
+    MessageHandlerFunc_t mMessageFunc;
+
+    struct {
+        Element *U8;
+        Element *I8;
+        Element *U16;
+        Element *I16;
+        Element *U32;
+        Element *I32;
+        Element *U64;
+        Element *I64;
+        Element *F32;
+        Element *F64;
+        Element *BOOLEAN;
+
+        Element *ELEMENT;
+        Element *TYPE;
+        Element *ALLOCATION;
+        Element *SAMPLER;
+        Element *SCRIPT;
+        Element *MESH;
+        Element *PROGRAM_FRAGMENT;
+        Element *PROGRAM_VERTEX;
+        Element *PROGRAM_RASTER;
+        Element *PROGRAM_STORE;
+
+        Element *A_8;
+        Element *RGB_565;
+        Element *RGB_888;
+        Element *RGBA_5551;
+        Element *RGBA_4444;
+        Element *RGBA_8888;
+
+        Element *FLOAT_2;
+        Element *FLOAT_3;
+        Element *FLOAT_4;
+
+        Element *DOUBLE_2;
+        Element *DOUBLE_3;
+        Element *DOUBLE_4;
+
+        Element *UCHAR_2;
+        Element *UCHAR_3;
+        Element *UCHAR_4;
+
+        Element *CHAR_2;
+        Element *CHAR_3;
+        Element *CHAR_4;
+
+        Element *USHORT_2;
+        Element *USHORT_3;
+        Element *USHORT_4;
+
+        Element *SHORT_2;
+        Element *SHORT_3;
+        Element *SHORT_4;
+
+        Element *UINT_2;
+        Element *UINT_3;
+        Element *UINT_4;
+
+        Element *INT_2;
+        Element *INT_3;
+        Element *INT_4;
+
+        Element *ULONG_2;
+        Element *ULONG_3;
+        Element *ULONG_4;
+
+        Element *LONG_2;
+        Element *LONG_3;
+        Element *LONG_4;
+
+        Element *MATRIX_4X4;
+        Element *MATRIX_3X3;
+        Element *MATRIX_2X2;
+    } mElements;
+
+
+
+    void throwError(const char *err) const;
+
+    static void * threadProc(void *);
+
+};
+
+#endif
+
diff --git a/libs/rs/Script.cpp b/libs/rs/Script.cpp
new file mode 100644
index 0000000..b6112dd
--- /dev/null
+++ b/libs/rs/Script.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+#include <malloc.h>
+
+#include "RenderScript.h"
+#include "Element.h"
+#include "Type.h"
+#include "Allocation.h"
+#include "Script.h"
+
+void Script::invoke(uint32_t slot, const void *v, size_t len) {
+    rsScriptInvokeV(mRS->mContext, getID(), slot, v, len);
+}
+
+void Script::forEach(uint32_t slot, const Allocation *ain, const Allocation *aout,
+                       const void *usr, size_t usrLen) {
+    if ((ain == NULL) && (aout == NULL)) {
+        mRS->throwError("At least one of ain or aout is required to be non-null.");
+    }
+    void *in_id = BaseObj::getObjID(ain);
+    void *out_id = BaseObj::getObjID(aout);
+    rsScriptForEach(mRS->mContext, getID(), slot, in_id, out_id, usr, usrLen);
+}
+
+
+Script::Script(void *id, RenderScript *rs) : BaseObj(id, rs) {
+}
+
+
+void Script::bindAllocation(const Allocation *va, uint32_t slot) {
+    rsScriptBindAllocation(mRS->mContext, getID(), BaseObj::getObjID(va), slot);
+}
+
+
+void Script::setVar(uint32_t index, const BaseObj *o) {
+    rsScriptSetVarObj(mRS->mContext, getID(), index, (o == NULL) ? 0 : o->getID());
+}
+
+void Script::setVar(uint32_t index, const void *v, size_t len) {
+    rsScriptSetVarV(mRS->mContext, getID(), index, v, len);
+}
+
+
+
+void Script::FieldBase::init(RenderScript *rs, uint32_t dimx, uint32_t usages) {
+    mAllocation = Allocation::createSized(rs, mElement, dimx, RS_ALLOCATION_USAGE_SCRIPT | usages);
+}
+
+//Script::FieldBase::FieldBase() {
+//}
+
+
diff --git a/libs/rs/Script.h b/libs/rs/Script.h
new file mode 100644
index 0000000..54d1e40
--- /dev/null
+++ b/libs/rs/Script.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_SCRIPT_H__
+#define __ANDROID_SCRIPT_H__
+
+#include <pthread.h>
+#include <rs.h>
+
+#include "RenderScript.h"
+#include "Allocation.h"
+
+class Type;
+class Element;
+class Allocation;
+
+class Script : public BaseObj {
+protected:
+    Script(void *id, RenderScript *rs);
+    void forEach(uint32_t slot, const Allocation *in, const Allocation *out, const void *v, size_t);
+    void bindAllocation(const Allocation *va, uint32_t slot);
+    void setVar(uint32_t index, const void *, size_t len);
+    void setVar(uint32_t index, const BaseObj *o);
+    void invoke(uint32_t slot, const void *v, size_t len);
+
+
+    void invoke(uint32_t slot) {
+        invoke(slot, NULL, 0);
+    }
+    void setVar(uint32_t index, float v) {
+        setVar(index, &v, sizeof(v));
+    }
+    void setVar(uint32_t index, double v) {
+        setVar(index, &v, sizeof(v));
+    }
+    void setVar(uint32_t index, int32_t v) {
+        setVar(index, &v, sizeof(v));
+    }
+    void setVar(uint32_t index, int64_t v) {
+        setVar(index, &v, sizeof(v));
+    }
+    void setVar(uint32_t index, bool v) {
+        setVar(index, &v, sizeof(v));
+    }
+
+public:
+    class FieldBase {
+    protected:
+        const Element *mElement;
+        Allocation *mAllocation;
+
+        void init(RenderScript *rs, uint32_t dimx, uint32_t usages = 0);
+
+    public:
+        const Element *getElement() {
+            return mElement;
+        }
+
+        const Type *getType() {
+            return mAllocation->getType();
+        }
+
+        const Allocation *getAllocation() {
+            return mAllocation;
+        }
+
+        //void updateAllocation();
+    };
+};
+
+#endif
diff --git a/libs/rs/ScriptC.cpp b/libs/rs/ScriptC.cpp
new file mode 100644
index 0000000..53d75b8
--- /dev/null
+++ b/libs/rs/ScriptC.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+#include <malloc.h>
+
+#include "ScriptC.h"
+
+ScriptC::ScriptC(RenderScript *rs,
+                 const char *codeTxt, size_t codeLength,
+                 const char *cachedName, size_t cachedNameLength,
+                 const char *cacheDir, size_t cacheDirLength)
+: Script(NULL, rs) {
+    mID = rsScriptCCreate(rs->mContext, cachedName, cachedNameLength,
+                          cacheDir, cacheDirLength, codeTxt, codeLength);
+}
+
diff --git a/libs/rs/ScriptC.h b/libs/rs/ScriptC.h
new file mode 100644
index 0000000..25f00ec
--- /dev/null
+++ b/libs/rs/ScriptC.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_SCRIPTC_H__
+#define __ANDROID_SCRIPTC_H__
+
+#include <pthread.h>
+#include <rs.h>
+
+#include "Script.h"
+
+class ScriptC : public Script {
+protected:
+    ScriptC(RenderScript *rs, void *txt, size_t len);
+    ScriptC(RenderScript *rs,
+            const char *codeTxt, size_t codeLength,
+            const char *cachedName, size_t cachedNameLength,
+            const char *cacheDir, size_t cacheDirLength);
+
+};
+
+#endif
diff --git a/libs/rs/Type.cpp b/libs/rs/Type.cpp
new file mode 100644
index 0000000..3249f97
--- /dev/null
+++ b/libs/rs/Type.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "RenderScript.h"
+#include "Element.h"
+#include "Type.h"
+
+void Type::calcElementCount() {
+    bool hasLod = hasMipmaps();
+    uint32_t x = getX();
+    uint32_t y = getY();
+    uint32_t z = getZ();
+    uint32_t faces = 1;
+    if (hasFaces()) {
+        faces = 6;
+    }
+    if (x == 0) {
+        x = 1;
+    }
+    if (y == 0) {
+        y = 1;
+    }
+    if (z == 0) {
+        z = 1;
+    }
+
+    uint32_t count = x * y * z * faces;
+    while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
+        if(x > 1) {
+            x >>= 1;
+        }
+        if(y > 1) {
+            y >>= 1;
+        }
+        if(z > 1) {
+            z >>= 1;
+        }
+
+        count += x * y * z * faces;
+    }
+    mElementCount = count;
+}
+
+
+Type::Type(void *id, RenderScript *rs) : BaseObj(id, rs) {
+    mDimX = 0;
+    mDimY = 0;
+    mDimZ = 0;
+    mDimMipmaps = false;
+    mDimFaces = false;
+    mElement = NULL;
+}
+
+void Type::updateFromNative() {
+    // We have 6 integer to obtain mDimX; mDimY; mDimZ;
+    // mDimLOD; mDimFaces; mElement;
+
+    /*
+    int[] dataBuffer = new int[6];
+    mRS.nTypeGetNativeData(getID(), dataBuffer);
+
+    mDimX = dataBuffer[0];
+    mDimY = dataBuffer[1];
+    mDimZ = dataBuffer[2];
+    mDimMipmaps = dataBuffer[3] == 1 ? true : false;
+    mDimFaces = dataBuffer[4] == 1 ? true : false;
+
+    int elementID = dataBuffer[5];
+    if(elementID != 0) {
+        mElement = new Element(elementID, mRS);
+        mElement.updateFromNative();
+    }
+    calcElementCount();
+    */
+}
+
+Type::Builder::Builder(RenderScript *rs, const Element *e) {
+    mRS = rs;
+    mElement = e;
+    mDimX = 0;
+    mDimY = 0;
+    mDimZ = 0;
+    mDimMipmaps = false;
+    mDimFaces = false;
+}
+
+void Type::Builder::setX(uint32_t value) {
+    if(value < 1) {
+        ALOGE("Values of less than 1 for Dimension X are not valid.");
+    }
+    mDimX = value;
+}
+
+void Type::Builder::setY(int value) {
+    if(value < 1) {
+        ALOGE("Values of less than 1 for Dimension Y are not valid.");
+    }
+    mDimY = value;
+}
+
+void Type::Builder::setMipmaps(bool value) {
+    mDimMipmaps = value;
+}
+
+void Type::Builder::setFaces(bool value) {
+    mDimFaces = value;
+}
+
+const Type * Type::Builder::create() {
+    ALOGE(" %i %i %i %i %i", mDimX, mDimY, mDimZ, mDimFaces, mDimMipmaps);
+    if (mDimZ > 0) {
+        if ((mDimX < 1) || (mDimY < 1)) {
+            ALOGE("Both X and Y dimension required when Z is present.");
+        }
+        if (mDimFaces) {
+            ALOGE("Cube maps not supported with 3D types.");
+        }
+    }
+    if (mDimY > 0) {
+        if (mDimX < 1) {
+            ALOGE("X dimension required when Y is present.");
+        }
+    }
+    if (mDimFaces) {
+        if (mDimY < 1) {
+            ALOGE("Cube maps require 2D Types.");
+        }
+    }
+
+    void * id = rsTypeCreate(mRS->mContext, mElement->getID(), mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces);
+    Type *t = new Type(id, mRS);
+    t->mElement = mElement;
+    t->mDimX = mDimX;
+    t->mDimY = mDimY;
+    t->mDimZ = mDimZ;
+    t->mDimMipmaps = mDimMipmaps;
+    t->mDimFaces = mDimFaces;
+
+    t->calcElementCount();
+    return t;
+}
+
diff --git a/libs/rs/Type.h b/libs/rs/Type.h
new file mode 100644
index 0000000..53481c3
--- /dev/null
+++ b/libs/rs/Type.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANDROID_TYPE_H__
+#define __ANDROID_TYPE_H__
+
+#include <rs.h>
+#include "RenderScript.h"
+#include "Element.h"
+
+class Type : public BaseObj {
+protected:
+    friend class Allocation;
+
+    uint32_t mDimX;
+    uint32_t mDimY;
+    uint32_t mDimZ;
+    bool mDimMipmaps;
+    bool mDimFaces;
+    size_t mElementCount;
+    const Element *mElement;
+
+    void calcElementCount();
+    virtual void updateFromNative();
+
+public:
+
+    const Element* getElement() const {
+        return mElement;
+    }
+
+    uint32_t getX() const {
+        return mDimX;
+    }
+
+    uint32_t getY() const {
+        return mDimY;
+    }
+
+    uint32_t getZ() const {
+        return mDimZ;
+    }
+
+    bool hasMipmaps() const {
+        return mDimMipmaps;
+    }
+
+    bool hasFaces() const {
+        return mDimFaces;
+    }
+
+    size_t getCount() const {
+        return mElementCount;
+    }
+
+    size_t getSizeBytes() const {
+        return mElementCount * mElement->getSizeBytes();
+    }
+
+
+    Type(void *id, RenderScript *rs);
+
+
+    class Builder {
+    protected:
+        RenderScript *mRS;
+        uint32_t mDimX;
+        uint32_t mDimY;
+        uint32_t mDimZ;
+        bool mDimMipmaps;
+        bool mDimFaces;
+        const Element *mElement;
+
+    public:
+        Builder(RenderScript *rs, const Element *e);
+
+        void setX(uint32_t value);
+        void setY(int value);
+        void setMipmaps(bool value);
+        void setFaces(bool value);
+        const Type * create();
+    };
+
+};
+
+#endif
diff --git a/libs/rs/tests/Android.mk b/libs/rs/tests/Android.mk
new file mode 100644
index 0000000..a773e84
--- /dev/null
+++ b/libs/rs/tests/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	compute.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libRS \
+	libz \
+	libcutils \
+	libutils \
+	libEGL \
+	libGLESv1_CM \
+	libGLESv2 \
+	libui \
+	libbcc \
+	libbcinfo \
+	libgui
+
+LOCAL_MODULE:= rstest-compute
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_C_INCLUDES +=  .. \
+	frameworks/base/libs/rs \
+	out/target/product/stingray/obj/SHARED_LIBRARIES/libRS_intermediates	
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/libs/rs/tests/compute.cpp b/libs/rs/tests/compute.cpp
new file mode 100644
index 0000000..28b135f
--- /dev/null
+++ b/libs/rs/tests/compute.cpp
@@ -0,0 +1,37 @@
+
+#include "RenderScript.h"
+#include "Element.h"
+#include "Type.h"
+#include "Allocation.h"
+
+int main(int argc, char** argv)
+{
+
+    RenderScript *rs = new RenderScript();
+    printf("New RS %p\n", rs);
+
+    bool r = rs->init(16);
+    printf("Init returned %i\n", r);
+
+    const Element *e = Element::RGBA_8888(rs);
+    printf("Element %p\n", e);
+
+    Type::Builder tb(rs, e);
+    tb.setX(128);
+    tb.setY(128);
+    const Type *t = tb.create();
+    printf("Type %p\n", t);
+
+
+    const Allocation *a1 = Allocation::createSized(rs, e, 1000);
+    printf("Allocation %p\n", a1);
+
+
+
+    printf("Deleting stuff\n");
+    delete t;
+    delete a1;
+    delete e;
+    delete rs;
+    printf("Delete OK\n");
+}
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 7a805aa..7cdb793 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -335,6 +335,10 @@
 }
 
 void OMXClient::disconnect() {
+    if (mOMX.get() != NULL) {
+        mOMX.clear();
+        mOMX = NULL;
+    }
 }
 
 }  // namespace android
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index 8b23dee..dde2066 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -4,7 +4,7 @@
 LOCAL_SRC_FILES:=                 \
         TextDescriptions.cpp      \
         TimedTextDriver.cpp       \
-        TimedTextInBandSource.cpp \
+        TimedText3GPPSource.cpp \
         TimedTextSource.cpp       \
         TimedTextSRTSource.cpp    \
         TimedTextPlayer.cpp
@@ -12,8 +12,7 @@
 LOCAL_CFLAGS += -Wno-multichar
 LOCAL_C_INCLUDES:= \
         $(JNI_H_INCLUDE) \
-        $(TOP)/frameworks/base/media/libstagefright \
-        $(TOP)/frameworks/base/include/media/stagefright/openmax
+        $(TOP)/frameworks/base/media/libstagefright
 
 LOCAL_MODULE:= libstagefright_timedtext
 
diff --git a/media/libstagefright/timedtext/TimedTextInBandSource.cpp b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
similarity index 63%
rename from media/libstagefright/timedtext/TimedTextInBandSource.cpp
rename to media/libstagefright/timedtext/TimedText3GPPSource.cpp
index afb73fb..4a3bfd3 100644
--- a/media/libstagefright/timedtext/TimedTextInBandSource.cpp
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "TimedTextInBandSource"
+#define LOG_TAG "TimedText3GPPSource"
 #include <utils/Log.h>
 
 #include <binder/Parcel.h>
@@ -26,19 +26,19 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 
-#include "TimedTextInBandSource.h"
+#include "TimedText3GPPSource.h"
 #include "TextDescriptions.h"
 
 namespace android {
 
-TimedTextInBandSource::TimedTextInBandSource(const sp<MediaSource>& mediaSource)
+TimedText3GPPSource::TimedText3GPPSource(const sp<MediaSource>& mediaSource)
     : mSource(mediaSource) {
 }
 
-TimedTextInBandSource::~TimedTextInBandSource() {
+TimedText3GPPSource::~TimedText3GPPSource() {
 }
 
-status_t TimedTextInBandSource::read(
+status_t TimedText3GPPSource::read(
         int64_t *timeUs, Parcel *parcel, const MediaSource::ReadOptions *options) {
     MediaBuffer *textBuffer = NULL;
     status_t err = mSource->read(&textBuffer, options);
@@ -60,7 +60,7 @@
 // text style for the string of text. These descriptions are present only
 // if they are needed. This method is used to extract the modifier
 // description and append it at the end of the text.
-status_t TimedTextInBandSource::extractAndAppendLocalDescriptions(
+status_t TimedText3GPPSource::extractAndAppendLocalDescriptions(
         int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel) {
     const void *data;
     size_t size = 0;
@@ -68,51 +68,46 @@
 
     const char *mime;
     CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+    CHECK(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0);
 
-    if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) {
-        data = textBuffer->data();
-        size = textBuffer->size();
+    data = textBuffer->data();
+    size = textBuffer->size();
 
-        if (size > 0) {
-            parcel->freeData();
-            flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
-            return TextDescriptions::getParcelOfDescriptions(
-                    (const uint8_t *)data, size, flag, timeUs / 1000, parcel);
-        }
-        return OK;
+    if (size > 0) {
+      parcel->freeData();
+      flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+      return TextDescriptions::getParcelOfDescriptions(
+          (const uint8_t *)data, size, flag, timeUs / 1000, parcel);
     }
-    return ERROR_UNSUPPORTED;
+    return OK;
 }
 
 // To extract and send the global text descriptions for all the text samples
 // in the text track or text file.
 // TODO: send error message to application via notifyListener()...?
-status_t TimedTextInBandSource::extractGlobalDescriptions(Parcel *parcel) {
+status_t TimedText3GPPSource::extractGlobalDescriptions(Parcel *parcel) {
     const void *data;
     size_t size = 0;
     int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS;
 
     const char *mime;
     CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+    CHECK(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0);
 
-    // support 3GPP only for now
-    if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) {
-        uint32_t type;
-        // get the 'tx3g' box content. This box contains the text descriptions
-        // used to render the text track
-        if (!mSource->getFormat()->findData(
-                kKeyTextFormatData, &type, &data, &size)) {
-            return ERROR_MALFORMED;
-        }
-
-        if (size > 0) {
-            flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
-            return TextDescriptions::getParcelOfDescriptions(
-                    (const uint8_t *)data, size, flag, 0, parcel);
-        }
-        return OK;
+    uint32_t type;
+    // get the 'tx3g' box content. This box contains the text descriptions
+    // used to render the text track
+    if (!mSource->getFormat()->findData(
+            kKeyTextFormatData, &type, &data, &size)) {
+        return ERROR_MALFORMED;
     }
-    return ERROR_UNSUPPORTED;
+
+    if (size > 0) {
+        flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+        return TextDescriptions::getParcelOfDescriptions(
+                (const uint8_t *)data, size, flag, 0, parcel);
+    }
+    return OK;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/timedtext/TimedTextInBandSource.h b/media/libstagefright/timedtext/TimedText3GPPSource.h
similarity index 80%
rename from media/libstagefright/timedtext/TimedTextInBandSource.h
rename to media/libstagefright/timedtext/TimedText3GPPSource.h
index 26e5737..cb7e47c 100644
--- a/media/libstagefright/timedtext/TimedTextInBandSource.h
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef TIMED_TEXT_IN_BAND_SOURCE_H_
-#define TIMED_TEXT_IN_BAND_SOURCE_H_
+#ifndef TIMED_TEXT_3GPP_SOURCE_H_
+#define TIMED_TEXT_3GPP_SOURCE_H_
 
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
@@ -27,9 +27,9 @@
 class MediaBuffer;
 class Parcel;
 
-class TimedTextInBandSource : public TimedTextSource {
+class TimedText3GPPSource : public TimedTextSource {
  public:
-  TimedTextInBandSource(const sp<MediaSource>& mediaSource);
+  TimedText3GPPSource(const sp<MediaSource>& mediaSource);
   virtual status_t start() { return mSource->start(); }
   virtual status_t stop() { return mSource->stop(); }
   virtual status_t read(
@@ -39,7 +39,7 @@
   virtual status_t extractGlobalDescriptions(Parcel *parcel);
 
  protected:
-  virtual ~TimedTextInBandSource();
+  virtual ~TimedText3GPPSource();
 
  private:
   sp<MediaSource> mSource;
@@ -47,9 +47,9 @@
   status_t extractAndAppendLocalDescriptions(
         int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel);
 
-  DISALLOW_EVIL_CONSTRUCTORS(TimedTextInBandSource);
+  DISALLOW_EVIL_CONSTRUCTORS(TimedText3GPPSource);
 };
 
 }  // namespace android
 
-#endif  // TIMED_TEXT_IN_BAND_SOURCE_H_
+#endif  // TIMED_TEXT_3GPP_SOURCE_H_
diff --git a/media/libstagefright/timedtext/TimedTextSource.cpp b/media/libstagefright/timedtext/TimedTextSource.cpp
index 9efe67c..ffbe1c3 100644
--- a/media/libstagefright/timedtext/TimedTextSource.cpp
+++ b/media/libstagefright/timedtext/TimedTextSource.cpp
@@ -18,12 +18,15 @@
 #define LOG_TAG "TimedTextSource"
 #include <utils/Log.h>
 
+#include <media/stagefright/foundation/ADebug.h>  // CHECK_XX macro
 #include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h>  // for MEDIA_MIMETYPE_xxx
 #include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
 
 #include "TimedTextSource.h"
 
-#include "TimedTextInBandSource.h"
+#include "TimedText3GPPSource.h"
 #include "TimedTextSRTSource.h"
 
 namespace android {
@@ -31,7 +34,13 @@
 // static
 sp<TimedTextSource> TimedTextSource::CreateTimedTextSource(
         const sp<MediaSource>& mediaSource) {
-    return new TimedTextInBandSource(mediaSource);
+    const char *mime;
+    CHECK(mediaSource->getFormat()->findCString(kKeyMIMEType, &mime));
+    if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) {
+        return new TimedText3GPPSource(mediaSource);
+    }
+    ALOGE("Unsupported mime type for subtitle. : %s", mime);
+    return NULL;
 }
 
 // static
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 455325a..c99aa02 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1129,7 +1129,8 @@
 
         public float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
                 long accessibilityNodeId, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid,
+                int prefetchFlags)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
             IAccessibilityInteractionConnection connection = null;
@@ -1150,7 +1151,7 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
-                        interactionId, callback, interrogatingPid, interrogatingTid);
+                        interactionId, callback, prefetchFlags, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3e6b872..4ee6953 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -42,7 +42,6 @@
 
 #define DEBUG_RESIZE    0
 
-
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -55,7 +54,7 @@
         mCurrentTransform(0),
         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
         mCurrentOpacity(true),
-        mRefreshPending(0),
+        mRefreshPending(false),
         mFrameLatencyNeeded(false),
         mFrameLatencyOffset(0),
         mFormat(PIXEL_FORMAT_NONE),
@@ -408,15 +407,9 @@
 // pageflip handling...
 // ----------------------------------------------------------------------------
 
-bool Layer::onPreComposition()
-{
-    // if there was more than one pending update, request a refresh
-    if (mRefreshPending >= 2) {
-        mRefreshPending = 0;
-        return true;
-    }
-    mRefreshPending = 0;
-    return false;
+bool Layer::onPreComposition() {
+    mRefreshPending = false;
+    return mQueuedFrames > 0;
 }
 
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
@@ -428,9 +421,11 @@
         // because we cannot call updateTeximage() without a corresponding
         // compositionComplete() call.
         // we'll trigger an update in onPreComposition().
-        if (mRefreshPending++) {
+        if (mRefreshPending) {
+            mPostedDirtyRegion.clear();
             return;
         }
+        mRefreshPending = true;
 
         // Capture the old state of the layer for comparisons later
         const bool oldOpacity = isOpaque();
@@ -541,25 +536,23 @@
 void Layer::unlockPageFlip(
         const Transform& planeTransform, Region& outDirtyRegion)
 {
-    if (mRefreshPending >= 2) {
-        return;
-    }
-
-    Region dirtyRegion(mPostedDirtyRegion);
-    if (!dirtyRegion.isEmpty()) {
+    Region postedRegion(mPostedDirtyRegion);
+    if (!postedRegion.isEmpty()) {
         mPostedDirtyRegion.clear();
-        // The dirty region is given in the layer's coordinate space
-        // transform the dirty region by the surface's transformation
-        // and the global transformation.
-        const Layer::State& s(drawingState());
-        const Transform tr(planeTransform * s.transform);
-        dirtyRegion = tr.transform(dirtyRegion);
+        if (!visibleRegionScreen.isEmpty()) {
+            // The dirty region is given in the layer's coordinate space
+            // transform the dirty region by the surface's transformation
+            // and the global transformation.
+            const Layer::State& s(drawingState());
+            const Transform tr(planeTransform * s.transform);
+            postedRegion = tr.transform(postedRegion);
 
-        // At this point, the dirty region is in screen space.
-        // Make sure it's constrained by the visible region (which
-        // is in screen space as well).
-        dirtyRegion.andSelf(visibleRegionScreen);
-        outDirtyRegion.orSelf(dirtyRegion);
+            // At this point, the dirty region is in screen space.
+            // Make sure it's constrained by the visible region (which
+            // is in screen space as well).
+            postedRegion.andSelf(visibleRegionScreen);
+            outDirtyRegion.orSelf(postedRegion);
+        }
     }
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index bf30608..39bbb2b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -116,7 +116,7 @@
     uint32_t mCurrentTransform;
     uint32_t mCurrentScalingMode;
     bool mCurrentOpacity;
-    size_t mRefreshPending;
+    bool mRefreshPending;
     bool mFrameLatencyNeeded;
     int mFrameLatencyOffset;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9e3f548..9d821dc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1000,6 +1000,12 @@
         drawWormhole();
     }
 
+    // FIXME: workaroud for b/6020860
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(0,0,0,0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    // end-workaround
+
     /*
      * and then, render the layers targeted at the framebuffer
      */
@@ -1776,6 +1782,10 @@
                 setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
                 return NO_ERROR;
             }
+            case 1006:{ // send empty update
+                signalRefresh();
+                return NO_ERROR;
+            }
             case 1008:  // toggle use of hw composer
                 n = data.readInt32();
                 mDebugDisableHWC = n ? 1 : 0;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
index b8ad823..9ab2a86 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
@@ -92,19 +92,24 @@
 
             canvas.restore();
 
-//            Path path = makePath();
-//            int r = mRandom.nextInt(10);
-//            if (r == 5 || r == 3) {
-//                mPathList.add(path);
-//            } else if (r == 9) {
-//                mPathList.clear();
-//            }
-//
-//            canvas.save();
-//            canvas.translate(550.0f + mRandom.nextInt(50), 60.0f + mRandom.nextInt(50));
-//            canvas.drawPath(path, mMediumPaint);
-//            canvas.restore();
-//            
+            for (int i = 0; i < mRandom.nextInt(20); i++) {
+                Path path = makePath();
+                int r = mRandom.nextInt(10);
+                if (r == 5 || r == 3) {
+                    mPathList.add(path);
+                }
+    
+                canvas.save();
+                canvas.translate(450.0f + mRandom.nextInt(200), mRandom.nextInt(200));
+                canvas.drawPath(path, mMediumPaint);
+                canvas.restore();
+            }
+
+            int r = mRandom.nextInt(100);
+            if (r == 50) {
+                mPathList.clear();
+            }
+
             invalidate();
         }
     }
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/unit_obj.a3d b/tests/RenderScriptTests/SceneGraph/res/raw/unit_obj.a3d
new file mode 100644
index 0000000..56eff04
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/unit_obj.a3d
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/SimpleAppRS.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/SimpleAppRS.java
index 621bfa36..fff6f34 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/SimpleAppRS.java
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/SimpleAppRS.java
@@ -34,9 +34,6 @@
 
 // This is where the scenegraph and the rendered objects are initialized and used
 public class SimpleAppRS {
-
-    private static String TAG = "SimpleAppRS";
-
     SceneManager mSceneManager;
 
     RenderScriptGL mRS;
@@ -44,6 +41,8 @@
 
     Scene mScene;
     Mesh mSimpleMesh;
+    Mesh mSphereMesh;
+    Mesh mCubeMesh;
 
     public void init(RenderScriptGL rs, Resources res, int width, int height) {
         mRS = rs;
@@ -54,7 +53,9 @@
         mScene = new Scene();
 
         setupGeometry();
-        setupRenderables();
+        setupColoredQuad();
+        setupTexturedQuad();
+        setupShadedGeometry();
         setupCamera();
         setupRenderPass();
 
@@ -68,6 +69,7 @@
         Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, 3,
                                                          Mesh.TriangleMeshBuilder.TEXTURE_0);
 
+        // Create four vertices with texture coordinates
         tmb.setTexture(0.0f, 1.0f).addVertex(-1.0f, 1.0f, 0.0f);
         tmb.setTexture(0.0f, 0.0f).addVertex(-1.0f, -1.0f, 0.0f);
         tmb.setTexture(1.0f, 0.0f).addVertex(1.0f, -1.0f, 0.0f);
@@ -76,36 +78,110 @@
         tmb.addTriangle(0, 1, 2);
         tmb.addTriangle(2, 3, 0);
         mSimpleMesh = tmb.create(true);
+
+        // Load a file that constains two pieces of geometry, a sphere and a cube
+        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.unit_obj);
+        for (int i = 0; i < model.getIndexEntryCount(); i ++) {
+            FileA3D.IndexEntry entry = model.getIndexEntry(i);
+            if (entry != null && entry.getName().equals("CubeMesh")) {
+                mCubeMesh = entry.getMesh();
+            } else if (entry != null && entry.getName().equals("SphereMesh")) {
+                mSphereMesh = entry.getMesh();
+            }
+        }
     }
 
-    private void setupRenderables() {
+    private void setupColoredQuad() {
         // Built-in shader that provides position, texcoord and normal
         VertexShader genericV = SceneManager.getDefaultVS();
         // Built-in shader that displays a color
         FragmentShader colorF = SceneManager.getColorFS();
-        // Built-in shader that displays a texture
-        FragmentShader textureF = SceneManager.getTextureFS();
         RenderState colorRS = new RenderState(genericV, colorF, null, null);
-        ProgramStore alphaBlend = ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS);
-        RenderState texRS = new RenderState(genericV, textureF, alphaBlend, null);
 
         // Draw a simple colored quad
         Renderable quad = mScene.appendNewRenderable();
         quad.setMesh(mSimpleMesh);
+        // Our shader has a constant input called "color"
+        // This tells the scenegraph to assign the following float3 to that input
         quad.appendSourceParams(new Float4Param("color", 0.2f, 0.3f, 0.4f));
         quad.setRenderState(colorRS);
+    }
+
+    private void setupTexturedQuad() {
+        // Built-in shader that provides position, texcoord and normal
+        VertexShader genericV = SceneManager.getDefaultVS();
+        // Built-in shader that displays a texture
+        FragmentShader textureF = SceneManager.getTextureFS();
+        // We want to use transparency based on the alpha channel of the texture
+        ProgramStore alphaBlend = ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS);
+        RenderState texRS = new RenderState(genericV, textureF, alphaBlend, null);
 
         // Draw a textured quad
-        quad = mScene.appendNewRenderable();
+        Renderable quad = mScene.appendNewRenderable();
         quad.setMesh(mSimpleMesh);
         // Make a transform to position the quad
         CompoundTransform t = mScene.appendNewCompoundTransform();
         t.addTranslate("position", new Float3(2, 2, 0));
         quad.setTransform(t);
+        // Our fragment shader has a constant texture input called "color"
+        // This will assign an icon from drawables to that input
         quad.appendSourceParams(new TextureParam("color", new Texture2D(R.drawable.icon)));
         quad.setRenderState(texRS);
     }
 
+    private FragmentShader createLambertShader() {
+        // Describe what constant inputs our shader wants
+        Element.Builder b = new Element.Builder(mRS);
+        b.add(Element.F32_4(mRS), "cameraPos");
+
+        // Create a shader from a text file in resources
+        FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
+        // Tell the shader what constants we want
+        fb.setShaderConst(new Type.Builder(mRS, b.create()).setX(1).create());
+        // Shader code location
+        fb.setShader(mRes, R.raw.diffuse);
+        // We want a texture called diffuse on our shader
+        fb.addTexture(TextureType.TEXTURE_2D, "diffuse");
+        FragmentShader shader = fb.create();
+        mScene.appendShader(shader);
+        return shader;
+    }
+
+    private void setupShadedGeometry() {
+        // Built-in shader that provides position, texcoord and normal
+        VertexShader genericV = SceneManager.getDefaultVS();
+        // Custom shader
+        FragmentShader diffuseF = createLambertShader();
+        RenderState diffuseRS = new RenderState(genericV, diffuseF, null, null);
+
+        // Draw a sphere
+        Renderable sphere = mScene.appendNewRenderable();
+        // Use the sphere geometry loaded earlier
+        sphere.setMesh(mSphereMesh);
+        // Make a transform to position the sphere
+        CompoundTransform t = mScene.appendNewCompoundTransform();
+        t.addTranslate("position", new Float3(-1, 2, 3));
+        t.addScale("scale", new Float3(1.4f, 1.4f, 1.4f));
+        sphere.setTransform(t);
+        // Tell the renderable which texture to use when we draw
+        // This will mean a texture param in the shader called "diffuse"
+        // will be assigned a texture called red.jpg
+        sphere.appendSourceParams(new TextureParam("diffuse", new Texture2D("", "red.jpg")));
+        sphere.setRenderState(diffuseRS);
+
+        // Draw a cube
+        Renderable cube = mScene.appendNewRenderable();
+        cube.setMesh(mCubeMesh);
+        t = mScene.appendNewCompoundTransform();
+        t.addTranslate("position", new Float3(-2, -2.1f, 0));
+        t.addRotate("rotateX", new Float3(1, 0, 0), 30);
+        t.addRotate("rotateY", new Float3(0, 1, 0), 30);
+        t.addScale("scale", new Float3(2, 2, 2));
+        cube.setTransform(t);
+        cube.appendSourceParams(new TextureParam("diffuse", new Texture2D("", "orange.jpg")));
+        cube.setRenderState(diffuseRS);
+    }
+
     private void setupCamera() {
         Camera camera = mScene.appendNewCamera();
         camera.setFar(200);
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 9ee6c84..8d7acee 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -21,7 +21,7 @@
 
 const char* const RESOURCES_ROOT_NAMESPACE = "http://schemas.android.com/apk/res/";
 const char* const RESOURCES_ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
-const char* const RESOURCES_AUTO_PACKAGE_NAMESPACE = "http://schemas.android.com/apk/res/auto";
+const char* const RESOURCES_AUTO_PACKAGE_NAMESPACE = "http://schemas.android.com/apk/res-auto";
 const char* const RESOURCES_ROOT_PRV_NAMESPACE = "http://schemas.android.com/apk/prv/res/";
 
 const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";