Merge "Remove dependency of libvideoeditor_jni.so on static libs from video editor engine" into jb-dev
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5085b1e..b29035d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2090,8 +2090,15 @@
                     r.activity.mCalled = false;
                     mInstrumentation.callActivityOnPause(r.activity);
                     // We need to keep around the original state, in case
-                    // we need to be created again.
-                    r.state = oldState;
+                    // we need to be created again.  But we only do this
+                    // for pre-Honeycomb apps, which always save their state
+                    // when pausing, so we can not have them save their state
+                    // when restarting from a paused state.  For HC and later,
+                    // we want to (and can) let the state be saved as the normal
+                    // part of stopping the activity.
+                    if (r.isPreHoneycomb()) {
+                        r.state = oldState;
+                    }
                     if (!r.activity.mCalled) {
                         throw new SuperNotCalledException(
                             "Activity " + r.intent.getComponent().toShortString() +
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index d3ba497..5e6b090 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -28,6 +28,7 @@
 import android.util.AndroidRuntimeException;
 import android.util.AttributeSet;
 import android.util.DebugUtils;
+import android.util.Log;
 import android.util.SparseArray;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -108,7 +109,9 @@
         mInstance.mRetainInstance = mRetainInstance;
         mInstance.mDetached = mDetached;
         mInstance.mFragmentManager = activity.mFragments;
-        
+        if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
+                "Instantiated fragment " + mInstance);
+
         return mInstance;
     }
     
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 7e1daa4..6058bdc 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1074,6 +1074,7 @@
             f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1));
             mActive.set(f.mIndex, f);
         }
+        if (DEBUG) Log.v(TAG, "Allocated fragment index " + f);
     }
     
     void makeInactive(Fragment f) {
@@ -1081,7 +1082,7 @@
             return;
         }
         
-        if (DEBUG) Log.v(TAG, "Freeing fragment index " + f.mIndex);
+        if (DEBUG) Log.v(TAG, "Freeing fragment index " + f);
         mActive.set(f.mIndex, null);
         if (mAvailIndices == null) {
             mAvailIndices = new ArrayList<Integer>();
@@ -1493,6 +1494,7 @@
                     fragments.add(f);
                     f.mRetaining = true;
                     f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
+                    if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
                 }
             }
         }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c791e47..da09a18 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -810,11 +810,17 @@
      * <p>
      * As a convenience, an Intent of this form can be created with the
      * {@link #createChooser} function.
-     * <p>Input: No data should be specified.  get*Extra must have
+     * <p>
+     * If the target {@link #EXTRA_INTENT} contains {@link ClipData}, you should
+     * also copy it to this intent along with relevant flags, such as
+     * {@link #FLAG_GRANT_READ_URI_PERMISSION}.
+     * <p>
+     * Input: No data should be specified.  get*Extra must have
      * a {@link #EXTRA_INTENT} field containing the Intent being executed,
      * and can optionally have a {@link #EXTRA_TITLE} field containing the
      * title text to display in the chooser.
-     * <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}.
+     * <p>
+     * Output: Depends on the protocol of {@link #EXTRA_INTENT}.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER";
@@ -835,8 +841,17 @@
         if (title != null) {
             intent.putExtra(EXTRA_TITLE, title);
         }
+
+        // Migrate any clip data and flags from target.
+        final ClipData targetClipData = target.getClipData();
+        if (targetClipData != null) {
+            intent.setClipData(targetClipData);
+            intent.addFlags(target.getFlags()
+                    & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION));
+        }
         return intent;
     }
+
     /**
      * Activity Action: Allow the user to select a particular kind of data and
      * return it.  This is different than {@link #ACTION_PICK} in that here we
@@ -6587,19 +6602,35 @@
 
     /**
      * Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and
-     * {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}.
+     * {@link #ACTION_SEND_MULTIPLE} to {@link ClipData}. Also inspects nested
+     * intents in {@link #ACTION_CHOOSER}.
      *
+     * @return Whether any contents were migrated.
      * @hide
      */
-    public void migrateExtraStreamToClipData() {
+    public boolean migrateExtraStreamToClipData() {
         // Refuse to touch if extras already parcelled
-        if (mExtras != null && mExtras.isParcelled()) return;
+        if (mExtras != null && mExtras.isParcelled()) return false;
 
         // Bail when someone already gave us ClipData
-        if (getClipData() != null) return;
+        if (getClipData() != null) return false;
 
         final String action = getAction();
-        if (ACTION_SEND.equals(action)) {
+        if (ACTION_CHOOSER.equals(action)) {
+            // Inspect target intent to see if we need to migrate
+            final Intent target = getParcelableExtra(EXTRA_INTENT);
+            if (target.migrateExtraStreamToClipData()) {
+                // Since we migrated in child, we need to promote ClipData and
+                // flags to ourselves to grant.
+                setClipData(target.getClipData());
+                addFlags(target.getFlags()
+                        & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION));
+                return true;
+            } else {
+                return false;
+            }
+
+        } else if (ACTION_SEND.equals(action)) {
             try {
                 final Uri stream = getParcelableExtra(EXTRA_STREAM);
                 final CharSequence text = getCharSequenceExtra(EXTRA_TEXT);
@@ -6610,6 +6641,7 @@
                             new ClipData.Item(text, htmlText, null, stream));
                     setClipData(clipData);
                     addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+                    return true;
                 }
             } catch (ClassCastException e) {
             }
@@ -6626,14 +6658,14 @@
                 if (texts != null) {
                     if (num >= 0 && num != texts.size()) {
                         // Wha...!  F- you.
-                        return;
+                        return false;
                     }
                     num = texts.size();
                 }
                 if (htmlTexts != null) {
                     if (num >= 0 && num != htmlTexts.size()) {
                         // Wha...!  F- you.
-                        return;
+                        return false;
                     }
                     num = htmlTexts.size();
                 }
@@ -6648,10 +6680,13 @@
 
                     setClipData(clipData);
                     addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+                    return true;
                 }
             } catch (ClassCastException e) {
             }
         }
+
+        return false;
     }
 
     private static ClipData.Item makeClipItem(ArrayList<Uri> streams, ArrayList<CharSequence> texts,
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index e1f1db2..16f9a18 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -491,20 +491,28 @@
                 if ((direction & View.FOCUS_ACCESSIBILITY) ==  View.FOCUS_ACCESSIBILITY) {
                     AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                     if (provider != null) {
-                        next = provider.accessibilityFocusSearch(direction,
-                                virtualDescendantId);
-                    } else if (virtualDescendantId == View.NO_ID) {
-                        View nextView = root.focusSearch(direction);
-                        if (nextView != null) {
-                            // If the focus search reached a node with a provider
-                            // we delegate to the provider to find the next one.
-                            provider = nextView.getAccessibilityNodeProvider();
-                            if (provider != null) {
-                                next = provider.accessibilityFocusSearch(direction,
-                                        virtualDescendantId);
-                            } else {
-                                next = nextView.createAccessibilityNodeInfo();
-                             }
+                        next = provider.accessibilityFocusSearch(direction, virtualDescendantId);
+                        if (next != null) {
+                            return;
+                        }
+                    }
+                    View nextView = root.focusSearch(direction);
+                    while (nextView != null) {
+                        // If the focus search reached a node with a provider
+                        // we delegate to the provider to find the next one.
+                        // If the provider does not return a virtual view to
+                        // take accessibility focus we try the next view found
+                        // by the focus search algorithm.
+                        provider = nextView.getAccessibilityNodeProvider();
+                        if (provider != null) {
+                            next = provider.accessibilityFocusSearch(direction, View.NO_ID);
+                            if (next != null) {
+                                break;
+                            }
+                            nextView = nextView.focusSearch(direction);
+                        } else {
+                            next = nextView.createAccessibilityNodeInfo();
+                            break;
                         }
                     }
                 } else {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 14523d3..a4fcd41 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6027,7 +6027,7 @@
             return;
         }
         if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
-            if (canTakeAccessibilityFocusFromHover()) {
+            if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
                 views.add(this);
                 return;
             }
@@ -6156,12 +6156,15 @@
      * @hide
      */
     public void clearAccessibilityFocus() {
-        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
-            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
-            ViewRootImpl viewRootImpl = getViewRootImpl();
-            if (viewRootImpl != null) {
+        ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl != null) {
+            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
+            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
                 viewRootImpl.setAccessibilityFocusedHost(null);
             }
+        }
+        if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
+            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
             invalidate();
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
             notifyAccessibilityStateChanged();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f86e036..41cd887 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -488,7 +488,9 @@
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
-                
+
+                setAccessibilityFocusedHost(null);
+
                 if (view instanceof RootViewSurfaceTaker) {
                     mSurfaceHolderCallback =
                             ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
@@ -556,6 +558,7 @@
                     mInputChannel = null;
                     mFallbackEventHandler.setView(null);
                     unscheduleTraversals();
+                    setAccessibilityFocusedHost(null);
                     throw new RuntimeException("Adding window failed", e);
                 } finally {
                     if (restore) {
@@ -575,6 +578,7 @@
                     mAdded = false;
                     mFallbackEventHandler.setView(null);
                     unscheduleTraversals();
+                    setAccessibilityFocusedHost(null);
                     switch (res) {
                         case WindowManagerImpl.ADD_BAD_APP_TOKEN:
                         case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
@@ -635,8 +639,6 @@
                 if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
                     view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
                 }
-
-                setAccessibilityFocusedHost(null);
             }
         }
     }
@@ -1853,18 +1855,15 @@
                 performDraw();
             }
         } else {
-            // End any pending transitions on this non-visible window
-            if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
+            if (viewVisibility == View.VISIBLE) {
+                // Try again
+                scheduleTraversals();
+            } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                 for (int i = 0; i < mPendingTransitions.size(); ++i) {
                     mPendingTransitions.get(i).endChangingAnimations();
                 }
                 mPendingTransitions.clear();
             }
-
-            if (viewVisibility == View.VISIBLE) {
-                // Try again
-                scheduleTraversals();
-            }
         }
     }
 
@@ -2543,11 +2542,51 @@
     }
 
     void setAccessibilityFocusedHost(View host) {
-        if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView == null) {
+        // If we have a virtual view with accessibility focus we need
+        // to clear the focus and invalidate the virtual view bounds.
+        if (mAccessibilityFocusedVirtualView != null) {
+
+            AccessibilityNodeInfo focusNode = mAccessibilityFocusedVirtualView;
+            View focusHost = mAccessibilityFocusedHost;
+            focusHost.clearAccessibilityFocusNoCallbacks();
+
+            // Wipe the state of the current accessibility focus since
+            // the call into the provider to clear accessibility focus
+            // will fire an accessibility event which will end up calling
+            // this method and we want to have clean state when this
+            // invocation happens.
+            mAccessibilityFocusedHost = null;
+            mAccessibilityFocusedVirtualView = null;
+
+            AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider();
+            if (provider != null) {
+                // Invalidate the area of the cleared accessibility focus.
+                focusNode.getBoundsInParent(mTempRect);
+                focusHost.invalidate(mTempRect);
+                // Clear accessibility focus in the virtual node.
+                final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
+                        focusNode.getSourceNodeId());
+                provider.performAction(virtualNodeId,
+                        AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
+            }
+        }
+        if (mAccessibilityFocusedHost != null) {
+            // Clear accessibility focus in the view.
             mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks();
         }
+
+        // Set the new focus host.
         mAccessibilityFocusedHost = host;
-        mAccessibilityFocusedVirtualView = null;
+
+        // If the host has a provide find the virtual descendant that has focus.
+        if (mAccessibilityFocusedHost != null) {
+            AccessibilityNodeProvider provider =
+                mAccessibilityFocusedHost.getAccessibilityNodeProvider();
+            if (provider != null) {
+                mAccessibilityFocusedVirtualView = provider.findAccessibilityFocus(View.NO_ID);
+                return;
+            }
+        }
     }
 
     public void requestChildFocus(View child, View focused) {
@@ -2633,6 +2672,8 @@
 
         destroyHardwareRenderer();
 
+        setAccessibilityFocusedHost(null);
+
         mView = null;
         mAttachInfo.mRootView = null;
         mAttachInfo.mSurface = null;
@@ -4608,6 +4649,31 @@
         if (mView == null) {
             return false;
         }
+        // Watch for accessibility focus change events from virtual nodes
+        // to keep track of accessibility focus being on a virtual node.
+        final int eventType = event.getEventType();
+        switch (eventType) {
+            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+                final long sourceId = event.getSourceNodeId();
+                // If the event is not from a virtual node we are not interested.
+                final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(sourceId);
+                if (virtualViewId == AccessibilityNodeInfo.UNDEFINED) {
+                    break;
+                }
+                final int realViewId = AccessibilityNodeInfo.getAccessibilityViewId(sourceId);
+                View focusHost = mView.findViewByAccessibilityId(realViewId);
+                setAccessibilityFocusedHost(focusHost);
+            } break;
+            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
+                final long sourceId = event.getSourceNodeId();
+                // If the event is not from a virtual node we are not interested.
+                final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(sourceId);
+                if (virtualViewId == AccessibilityNodeInfo.UNDEFINED) {
+                    break;
+                }
+                setAccessibilityFocusedHost(null);
+            } break;
+        }
         mAccessibilityManager.sendAccessibilityEvent(event);
         return true;
     }
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index f4796d5..5d42da1 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -7986,7 +7986,9 @@
         }
         nativeSetTextSelection(mNativeClass, data.mSelectTextPtr);
 
-        if (data.mSelectionReason == TextSelectionData.REASON_ACCESSIBILITY_INJECTOR) {
+        if ((data.mSelectionReason == TextSelectionData.REASON_ACCESSIBILITY_INJECTOR)
+                || (!mSelectingText
+                        && data.mSelectionReason != TextSelectionData.REASON_SELECT_WORD)) {
             selectionDone();
             mShowTextSelectionExtra = true;
             invalidate();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 4adfd6a..7aa9a0b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -22,7 +22,6 @@
 import android.database.Cursor;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.Region;
 import android.media.MediaFile;
 import android.net.ProxyProperties;
 import android.net.Uri;
@@ -864,6 +863,7 @@
     static class TextSelectionData {
         static final int REASON_UNKNOWN = 0;
         static final int REASON_ACCESSIBILITY_INJECTOR = 1;
+        static final int REASON_SELECT_WORD = 2;
         public TextSelectionData(int start, int end, int selectTextPtr) {
             mStart = start;
             mEnd = end;
@@ -1718,12 +1718,16 @@
                             break;
                         }
                         case SELECT_WORD_AT: {
+                            mTextSelectionChangeReason
+                                    = TextSelectionData.REASON_SELECT_WORD;
                             int x = msg.arg1;
                             int y = msg.arg2;
                             if (!nativeSelectWordAt(mNativeClass, x, y)) {
                                 mWebViewClassic.mPrivateHandler.obtainMessage(WebViewClassic.SHOW_CARET_HANDLE)
                                     .sendToTarget();
                             }
+                            mTextSelectionChangeReason
+                                    = TextSelectionData.REASON_UNKNOWN;
                             break;
                         }
                         case SELECT_ALL:
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ab9d370..04c8cdc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1480,6 +1480,9 @@
 
     @Override
     public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
         switch (action) {
             case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
                 if (getLastVisiblePosition() < getCount() - 1) {
@@ -1496,7 +1499,7 @@
                 }
             } return false;
         }
-        return super.performAccessibilityAction(action, arguments);
+        return false;
     }
 
     /**
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index c6104bc..fe6c4f5 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -765,16 +765,6 @@
     }
 
     /**
-     * Gets whether the given observer is already registered.
-     *
-     * @param observer The observer.
-     * @return True if already registered.
-     */
-    public boolean isRegisteredObserver(DataSetObserver observer) {
-        return mObservers.contains(observer);
-    }
-
-    /**
      * Represents a record in the history.
      */
     public final static class HistoricalRecord {
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 0c0bb1e..be6b4e2 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -20,10 +20,8 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
@@ -176,11 +174,6 @@
     private int mDefaultActionButtonContentDescription;
 
     /**
-     * Whether this view has a default activity affordance.
-     */
-    private boolean mHasDefaultActivity;
-
-    /**
      * Create a new instance.
      *
      * @param context The application environment.
@@ -252,8 +245,6 @@
         Resources resources = context.getResources();
         mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
               resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
-
-        updateHasDefaultActivity();
     }
 
     /**
@@ -267,21 +258,6 @@
         }
     }
 
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        Configuration oldConfig = mContext.getResources().getConfiguration();
-        final int changed = oldConfig.diff(newConfig);
-        if ((changed & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
-                || (changed & ActivityInfo.CONFIG_ORIENTATION) != 0) {
-            updateHasDefaultActivity();
-        }
-    }
-
-    private void updateHasDefaultActivity() {
-        mHasDefaultActivity = mContext.getResources().getBoolean(
-                R.bool.activity_chooser_view_has_default_activity);
-    }
-
     /**
      * Sets the background for the button that expands the activity
      * overflow list.
@@ -407,8 +383,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         ActivityChooserModel dataModel = mAdapter.getDataModel();
-        if (dataModel != null
-                && !dataModel.isRegisteredObserver(mModelDataSetOberver)) {
+        if (dataModel != null) {
             dataModel.registerObserver(mModelDataSetOberver);
         }
         mIsAttachedToWindow = true;
@@ -418,8 +393,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         ActivityChooserModel dataModel = mAdapter.getDataModel();
-        if (dataModel != null
-                && dataModel.isRegisteredObserver(mModelDataSetOberver)) {
+        if (dataModel != null) {
             dataModel.unregisterObserver(mModelDataSetOberver);
         }
         ViewTreeObserver viewTreeObserver = getViewTreeObserver();
@@ -522,7 +496,7 @@
         // Default activity button.
         final int activityCount = mAdapter.getActivityCount();
         final int historySize = mAdapter.getHistorySize();
-        if (mHasDefaultActivity && activityCount > 0 && historySize > 0) {
+        if (activityCount > 0 && historySize > 0) {
             mDefaultActivityButton.setVisibility(VISIBLE);
             ResolveInfo activity = mAdapter.getDefaultActivity();
             PackageManager packageManager = mContext.getPackageManager();
@@ -538,9 +512,9 @@
         }
         // Activity chooser content.
         if (mDefaultActivityButton.getVisibility() == VISIBLE) {
-            mActivityChooserContent.setBackground(mActivityChooserContentBackground);
+            mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
         } else {
-            mActivityChooserContent.setBackground(null);
+            mActivityChooserContent.setBackgroundDrawable(null);
         }
     }
 
@@ -603,7 +577,7 @@
         // OnLongClickListener#onLongClick
         @Override
         public boolean onLongClick(View view) {
-            if (mHasDefaultActivity && view == mDefaultActivityButton) {
+            if (view == mDefaultActivityButton) {
                 if (mAdapter.getCount() > 0) {
                     mIsSelectingDefaultActivity = true;
                     showPopupUnchecked(mInitialActivityCount);
@@ -656,16 +630,14 @@
 
         public void setDataModel(ActivityChooserModel dataModel) {
             ActivityChooserModel oldDataModel = mAdapter.getDataModel();
-            if (oldDataModel != null) {
+            if (oldDataModel != null && isShown()) {
                 oldDataModel.unregisterObserver(mModelDataSetOberver);
             }
             mDataModel = dataModel;
-            if (dataModel != null) {
+            if (dataModel != null && isShown()) {
                 dataModel.registerObserver(mModelDataSetOberver);
-                notifyDataSetChanged();
-            } else {
-                notifyDataSetInvalidated();
             }
+            notifyDataSetChanged();
         }
 
         @Override
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 03fdc39..b2c8164 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -1367,6 +1368,35 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(Gallery.class.getName());
+        info.setScrollable(mItemCount > 1);
+        if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+        }
+        if (mItemCount > 0 && mSelectedPosition > 0) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
+                    final int currentChildIndex = mSelectedPosition - mFirstPosition;
+                    return scrollToChild(currentChildIndex + 1);
+                }
+            } return false;
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                if (mItemCount > 0 && mSelectedPosition > 0) {
+                    final int currentChildIndex = mSelectedPosition - mFirstPosition;
+                    return scrollToChild(currentChildIndex - 1);
+                }
+            } return false;
+        }
+        return false;
     }
 
     /**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index ffabd1d9..f889cb7 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -739,6 +739,9 @@
 
     @Override
     public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
         switch (action) {
             case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
                 final int viewportWidth = getWidth() - mPaddingLeft - mPaddingRight;
@@ -757,7 +760,7 @@
                 }
             } return false;
         }
-        return super.performAccessibilityAction(action, arguments);
+        return false;
     }
 
     @Override
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 7c809b3..b825e1b 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -950,6 +950,8 @@
                     provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
                             AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                     mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
+                    provider.performAction(hoveredVirtualViewId,
+                            AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
                 } break;
                 case MotionEvent.ACTION_HOVER_MOVE: {
                     if (mLastHoveredChildVirtualViewId != hoveredVirtualViewId
@@ -960,6 +962,8 @@
                         provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
                                 AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                         mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
+                        provider.performAction(hoveredVirtualViewId,
+                                AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
                     }
                 } break;
                 case MotionEvent.ACTION_HOVER_EXIT: {
@@ -1413,9 +1417,16 @@
     }
 
     @Override
-    public void sendAccessibilityEvent(int eventType) {
-        // Do not send accessibility events - we want the user to
-        // perceive this widget as several controls rather as a whole.
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        // We do not want the real descendant to be considered focus search
+        // since it is managed by the accessibility node provider.
+        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
+            if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
+                views.add(this);
+                return;
+            }
+        }
+        super.addFocusables(views, direction, focusableMode);
     }
 
     @Override
@@ -2072,7 +2083,12 @@
         }
     }
 
+    /**
+     * Class for managing virtual view tree rooted at this picker.
+     */
     class AccessibilityNodeProviderImpl extends AccessibilityNodeProvider {
+        private static final int UNDEFINED = Integer.MIN_VALUE;
+
         private static final int VIRTUAL_VIEW_ID_INCREMENT = 1;
 
         private static final int VIRTUAL_VIEW_ID_INPUT = 2;
@@ -2083,6 +2099,8 @@
 
         private final int[] mTempArray = new int[2];
 
+        private int mAccessibilityFocusedView = UNDEFINED;
+
         @Override
         public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
             switch (virtualViewId) {
@@ -2137,6 +2155,37 @@
         @Override
         public boolean performAction(int virtualViewId, int action, Bundle arguments) {
             switch (virtualViewId) {
+                case View.NO_ID: {
+                    switch (action) {
+                        case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView != virtualViewId) {
+                                mAccessibilityFocusedView = virtualViewId;
+                                requestAccessibilityFocus();
+                                return true;
+                            }
+                        } return false;
+                        case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView == virtualViewId) {
+                                mAccessibilityFocusedView = UNDEFINED;
+                                clearAccessibilityFocus();
+                                return true;
+                            }
+                            return false;
+                        }
+                        case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                            if (getWrapSelectorWheel() || getValue() < getMaxValue()) {
+                                changeValueByOne(true);
+                                return true;
+                            }
+                        } return false;
+                        case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                            if (getWrapSelectorWheel() || getValue() > getMinValue()) {
+                                changeValueByOne(false);
+                                return true;
+                            }
+                        } return false;
+                    }
+                } break;
                 case VIRTUAL_VIEW_ID_INPUT: {
                     switch (action) {
                         case AccessibilityNodeInfo.ACTION_FOCUS: {
@@ -2149,25 +2198,182 @@
                                 mInputText.clearFocus();
                                 return true;
                             }
-                        } break;
+                            return false;
+                        }
+                        case AccessibilityNodeInfo.ACTION_CLICK: {
+                            showSoftInput();
+                            return true;
+                        }
+                        case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView != virtualViewId) {
+                                mAccessibilityFocusedView = virtualViewId;
+                                sendAccessibilityEventForVirtualView(virtualViewId,
+                                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+                                mInputText.invalidate();
+                                return true;
+                            }
+                        } return false;
+                        case  AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView == virtualViewId) {
+                                mAccessibilityFocusedView = UNDEFINED;
+                                sendAccessibilityEventForVirtualView(virtualViewId,
+                                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+                                mInputText.invalidate();
+                                return true;
+                            }
+                        } return false;
+                        default: {
+                            return mInputText.performAccessibilityAction(action, arguments);
+                        }
+                    }
+                } return false;
+                case VIRTUAL_VIEW_ID_INCREMENT: {
+                    switch (action) {
+                        case AccessibilityNodeInfo.ACTION_CLICK: {
+                            NumberPicker.this.changeValueByOne(true);
+                            sendAccessibilityEventForVirtualView(virtualViewId,
+                                    AccessibilityEvent.TYPE_VIEW_CLICKED);
+                        } return true;
+                        case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView != virtualViewId) {
+                                mAccessibilityFocusedView = virtualViewId;
+                                sendAccessibilityEventForVirtualView(virtualViewId,
+                                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+                                invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+                                return true;
+                            }
+                        } return false;
+                        case  AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView == virtualViewId) {
+                                mAccessibilityFocusedView = UNDEFINED;
+                                sendAccessibilityEventForVirtualView(virtualViewId,
+                                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+                                invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+                                return true;
+                            }
+                        } return false;
+                    }
+                } return false;
+                case VIRTUAL_VIEW_ID_DECREMENT: {
+                    switch (action) {
+                        case AccessibilityNodeInfo.ACTION_CLICK: {
+                            final boolean increment = (virtualViewId == VIRTUAL_VIEW_ID_INCREMENT);
+                            NumberPicker.this.changeValueByOne(increment);
+                            sendAccessibilityEventForVirtualView(virtualViewId,
+                                    AccessibilityEvent.TYPE_VIEW_CLICKED);
+                        } return true;
+                        case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView != virtualViewId) {
+                                mAccessibilityFocusedView = virtualViewId;
+                                sendAccessibilityEventForVirtualView(virtualViewId,
+                                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+                                invalidate(0, 0, mRight, mTopSelectionDividerTop);
+                                return true;
+                            }
+                        } return false;
+                        case  AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
+                            if (mAccessibilityFocusedView == virtualViewId) {
+                                mAccessibilityFocusedView = UNDEFINED;
+                                sendAccessibilityEventForVirtualView(virtualViewId,
+                                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+                                invalidate(0, 0, mRight, mTopSelectionDividerTop);
+                                return true;
+                            }
+                        } return false;
+                    }
+                } return false;
+            }
+            return super.performAction(virtualViewId, action, arguments);
+        }
+
+        @Override
+        public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
+            return createAccessibilityNodeInfo(mAccessibilityFocusedView);
+        }
+
+        @Override
+        public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
+            switch (direction) {
+                case View.ACCESSIBILITY_FOCUS_DOWN:
+                case View.ACCESSIBILITY_FOCUS_FORWARD: {
+                    switch (mAccessibilityFocusedView) {
+                        case UNDEFINED: {
+                            return createAccessibilityNodeInfo(View.NO_ID);
+                        }
+                        case View.NO_ID: {
+                            if (hasVirtualDecrementButton()) {
+                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
+                            }
+                        }
+                        //$FALL-THROUGH$
+                        case VIRTUAL_VIEW_ID_DECREMENT: {
+                            return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
+                        }
+                        case VIRTUAL_VIEW_ID_INPUT: {
+                            if (hasVirtualIncrementButton()) {
+                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
+                            }
+                        }
+                        //$FALL-THROUGH$
+                        case VIRTUAL_VIEW_ID_INCREMENT: {
+                            View nextFocus = NumberPicker.this.focusSearch(direction);
+                            if (nextFocus != null) {
+                                return nextFocus.createAccessibilityNodeInfo();
+                            }
+                            return null;
+                        }
+                    }
+                } break;
+                case View.ACCESSIBILITY_FOCUS_UP:
+                case View.ACCESSIBILITY_FOCUS_BACKWARD: {
+                    switch (mAccessibilityFocusedView) {
+                        case UNDEFINED: {
+                            return createAccessibilityNodeInfo(View.NO_ID);
+                        }
+                        case View.NO_ID: {
+                            if (hasVirtualIncrementButton()) {
+                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
+                            }
+                        }
+                        //$FALL-THROUGH$
+                        case VIRTUAL_VIEW_ID_INCREMENT: {
+                            return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
+                        }
+                        case VIRTUAL_VIEW_ID_INPUT: {
+                            if (hasVirtualDecrementButton()) {
+                                return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
+                            }
+                        }
+                        //$FALL-THROUGH$
+                        case VIRTUAL_VIEW_ID_DECREMENT: {
+                            View nextFocus = NumberPicker.this.focusSearch(direction);
+                            if (nextFocus != null) {
+                                return nextFocus.createAccessibilityNodeInfo();
+                            }
+                            return null;
+                        }
                     }
                 } break;
             }
-            return super.performAction(virtualViewId, action, arguments);
+            return null;
         }
 
         public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) {
             switch (virtualViewId) {
                 case VIRTUAL_VIEW_ID_DECREMENT: {
-                    sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
-                            getVirtualDecrementButtonText());
+                    if (hasVirtualDecrementButton()) {
+                        sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
+                                getVirtualDecrementButtonText());
+                    }
                 } break;
                 case VIRTUAL_VIEW_ID_INPUT: {
                     sendAccessibilityEventForVirtualText(eventType);
                 } break;
                 case VIRTUAL_VIEW_ID_INCREMENT: {
-                    sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
-                            getVirtualIncrementButtonText());
+                    if (hasVirtualIncrementButton()) {
+                        sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
+                                getVirtualIncrementButtonText());
+                    }
                 } break;
             }
         }
@@ -2227,8 +2433,13 @@
 
         private AccessibilityNodeInfo createAccessibiltyNodeInfoForInputText() {
             AccessibilityNodeInfo info = mInputText.createAccessibilityNodeInfo();
-            info.setLongClickable(true);
             info.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
+            if (mAccessibilityFocusedView != VIRTUAL_VIEW_ID_INPUT) {
+                info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+            }
+            if (mAccessibilityFocusedView == VIRTUAL_VIEW_ID_INPUT) {
+                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+            }
             return info;
         }
 
@@ -2252,6 +2463,15 @@
             getLocationOnScreen(locationOnScreen);
             boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
             info.setBoundsInScreen(boundsInScreen);
+
+            if (mAccessibilityFocusedView != virtualViewId) {
+                info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+            }
+            if (mAccessibilityFocusedView == virtualViewId) {
+                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+            }
+            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
+
             return info;
         }
 
@@ -2261,9 +2481,15 @@
             info.setClassName(NumberPicker.class.getName());
             info.setPackageName(mContext.getPackageName());
             info.setSource(NumberPicker.this);
-            info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT);
+
+            if (hasVirtualDecrementButton()) {
+                info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT);
+            }
             info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
-            info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
+            if (hasVirtualIncrementButton()) {
+                info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
+            }
+
             info.setParent((View) getParent());
             info.setEnabled(NumberPicker.this.isEnabled());
             info.setScrollable(true);
@@ -2276,9 +2502,31 @@
             getLocationOnScreen(locationOnScreen);
             boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
             info.setBoundsInScreen(boundsInScreen);
+
+            if (mAccessibilityFocusedView != View.NO_ID) {
+                info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+            }
+            if (mAccessibilityFocusedView == View.NO_ID) {
+                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+            }
+            if (getWrapSelectorWheel() || getValue() < getMaxValue()) {
+                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+            }
+            if (getWrapSelectorWheel() || getValue() > getMinValue()) {
+                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+            }
+
             return info;
         }
 
+        private boolean hasVirtualDecrementButton() {
+            return getWrapSelectorWheel() || getValue() > getMinValue();
+        }
+
+        private boolean hasVirtualIncrementButton() {
+            return getWrapSelectorWheel() || getValue() < getMaxValue();
+        }
+
         private String getVirtualDecrementButtonText() {
             int value = mValue - 1;
             if (mWrapSelectorWheel) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index b398ce4..a499743 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -742,6 +742,9 @@
 
     @Override
     public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
         switch (action) {
             case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
                 final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop;
@@ -760,7 +763,7 @@
                 }
             } return false;
         }
-        return super.performAccessibilityAction(action, arguments);
+        return false;
     }
 
     @Override
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 21840ca..4045497 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -44,7 +44,6 @@
  * <code>
  *  // In Activity#onCreateOptionsMenu
  *  public boolean onCreateOptionsMenu(Menu menu) {
- *      getManuInflater().inflate(R.menu.my_menu, menu);
  *      // Get the menu item.
  *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
  *      // Get the provider and hold onto it to set/change the share intent.
@@ -246,7 +245,7 @@
      * call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
      * action view. You should <strong>not</strong> call
      * {@link android.app.Activity#invalidateOptionsMenu()} from
-     * {@link android.app.Activity#onCreateOptionsMenu(Menu)}.
+     * {@link android.app.Activity#onCreateOptionsMenu(Menu)}."
      * <p>
      * <code>
      * private void doShare(Intent intent) {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 7ca02e1..74ea038 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -132,8 +132,6 @@
 
         // Restore SpellCheckSpans in pool
         for (int i = 0; i < mLength; i++) {
-            // Resets id and progress to invalidate spell check span
-            mSpellCheckSpans[i].setSpellCheckInProgress(false);
             mIds[i] = -1;
         }
         mLength = 0;
@@ -200,15 +198,16 @@
 
     private void addSpellCheckSpan(Editable editable, int start, int end) {
         final int index = nextSpellCheckSpanIndex();
-        editable.setSpan(mSpellCheckSpans[index], start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        SpellCheckSpan spellCheckSpan = mSpellCheckSpans[index];
+        editable.setSpan(spellCheckSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        spellCheckSpan.setSpellCheckInProgress(false);
         mIds[index] = mSpanSequenceCounter++;
     }
 
-    public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
+    public void onSpellCheckSpanRemoved(SpellCheckSpan spellCheckSpan) {
+        // Recycle any removed SpellCheckSpan (from this code or during text edition)
         for (int i = 0; i < mLength; i++) {
             if (mSpellCheckSpans[i] == spellCheckSpan) {
-                // Resets id and progress to invalidate spell check span
-                mSpellCheckSpans[i].setSpellCheckInProgress(false);
                 mIds[i] = -1;
                 return;
             }
@@ -387,6 +386,7 @@
             final SpellCheckSpan spellCheckSpan =
                     onGetSuggestionsInternal(results[i], USE_SPAN_RANGE, USE_SPAN_RANGE);
             if (spellCheckSpan != null) {
+                // onSpellCheckSpanRemoved will recycle this span in the pool
                 editable.removeSpan(spellCheckSpan);
             }
         }
@@ -414,11 +414,12 @@
                         suggestionsInfo, offset, length);
                 if (spellCheckSpan == null && scs != null) {
                     // the spellCheckSpan is shared by all the "SuggestionsInfo"s in the same
-                    // SentenceSuggestionsInfo
+                    // SentenceSuggestionsInfo. Removal is deferred after this loop.
                     spellCheckSpan = scs;
                 }
             }
             if (spellCheckSpan != null) {
+                // onSpellCheckSpanRemoved will recycle this span in the pool
                 editable.removeSpan(spellCheckSpan);
             }
         }
@@ -633,7 +634,8 @@
                             }
                             break;
                         }
-                        removeSpellCheckSpan(spellCheckSpan);
+                        // This spellCheckSpan is replaced by the one we are creating
+                        editable.removeSpan(spellCheckSpan);
                         spellCheckStart = Math.min(spanStart, spellCheckStart);
                         spellCheckEnd = Math.max(spanEnd, spellCheckEnd);
                     }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 22df3bc..dd0915b 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -32,6 +32,7 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.TableMaskFilter;
+import android.os.Bundle;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.InputDevice;
@@ -1228,6 +1229,35 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(StackView.class.getName());
+        info.setScrollable(getChildCount() > 1);
+        if (getDisplayedChild() < getChildCount() - 1) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+        }
+        if (getDisplayedChild() > 0) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                if (getDisplayedChild() < getChildCount() - 1) {
+                    showNext();
+                    return true;
+                }
+            } return false;
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                if (getDisplayedChild() > 0) {
+                    showPrevious();
+                    return true;
+                }
+            } return false;
+        }
+        return false;
     }
 
     class LayoutParams extends ViewGroup.LayoutParams {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index abf2eb2..fc56e11 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7240,7 +7240,7 @@
 
         if (mEditor != null && mEditor.mSpellChecker != null && newStart < 0 &&
                 what instanceof SpellCheckSpan) {
-            mEditor.mSpellChecker.removeSpellCheckSpan((SpellCheckSpan) what);
+            mEditor.mSpellChecker.onSpellCheckSpanRemoved((SpellCheckSpan) what);
         }
     }
 
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 89f2187..e9db9d9 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -19,13 +19,17 @@
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Vibrator;
-import android.view.MotionEvent;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
 import android.view.View;
-import android.view.ViewConfiguration;
+import android.view.ViewGroup;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 import android.widget.Toast;
 
 public class PlatLogoActivity extends Activity {
@@ -34,15 +38,65 @@
     int mCount;
     final Handler mHandler = new Handler();
 
+    private View makeView() {
+        DisplayMetrics metrics = new DisplayMetrics();
+        getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+        LinearLayout view = new LinearLayout(this);
+        view.setOrientation(LinearLayout.VERTICAL);
+        view.setLayoutParams(
+                new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.WRAP_CONTENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT
+                ));
+        final int p = (int)(8 * metrics.density);
+        view.setPadding(p, p, p, p);
+
+        Typeface light = Typeface.create("sans-serif-light", Typeface.NORMAL);
+        Typeface normal = Typeface.create("sans-serif", Typeface.BOLD);
+
+        final float size = 14 * metrics.density;
+        final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.WRAP_CONTENT,
+                LinearLayout.LayoutParams.WRAP_CONTENT);
+        lp.gravity = Gravity.CENTER_HORIZONTAL;
+        lp.bottomMargin = (int) (-4*metrics.density);
+
+        TextView tv = new TextView(this);
+        if (light != null) tv.setTypeface(light);
+        tv.setTextSize(1.25f*size);
+        tv.setTextColor(0xFFFFFFFF);
+        tv.setShadowLayer(4*metrics.density, 0, 2*metrics.density, 0x66000000);
+        tv.setText("Android " + Build.VERSION.RELEASE);
+        view.addView(tv, lp);
+   
+        tv = new TextView(this);
+        if (normal != null) tv.setTypeface(normal);
+        tv.setTextSize(size);
+        tv.setTextColor(0xFFFFFFFF);
+        tv.setShadowLayer(4*metrics.density, 0, 2*metrics.density, 0x66000000);
+        tv.setText("JELLY BEAN");
+        view.addView(tv, lp);
+
+        return view;
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mToast = Toast.makeText(this, "Android X.X: Jelly Bean", Toast.LENGTH_SHORT);
+        mToast = Toast.makeText(this, "", Toast.LENGTH_LONG);
+        mToast.setView(makeView());
+
+        DisplayMetrics metrics = new DisplayMetrics();
+        getWindowManager().getDefaultDisplay().getMetrics(metrics);
 
         mContent = new ImageView(this);
         mContent.setImageResource(com.android.internal.R.drawable.platlogo);
         mContent.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        
+        final int p = (int)(32 * metrics.density);
+        mContent.setPadding(p, p, p, p);
 
         mContent.setOnClickListener(new View.OnClickListener() {
             @Override
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index d8ec656..e3d11f2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -357,19 +357,26 @@
 static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jintArray colors, jint offset, jint stride,
         jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, SkPaint* paint) {
-    SkBitmap bitmap;
-    SkBitmap::Config config = hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config;
-    bitmap.setConfig(config, width, height);
+    SkBitmap* bitmap = new SkBitmap;
+    bitmap->setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config,
+            width, height);
 
-    if (!bitmap.allocPixels()) {
+    if (!bitmap->allocPixels()) {
+        delete bitmap;
         return;
     }
 
-    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, bitmap)) {
+    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
+        delete bitmap;
         return;
     }
 
-    renderer->drawBitmapData(&bitmap, left, top, paint);
+    renderer->drawBitmapData(bitmap, left, top, paint);
+
+    // If the renderer is a deferred renderer it will own the bitmap
+    if (!renderer->isDeferred()) {
+        delete bitmap;
+    }
 }
 
 static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 91e66bc..7b91022 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -44,6 +44,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
+        android:importantForAccessibility="no"
         />
 
     <!-- minute -->
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index c5727ea..d26666e 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -51,12 +51,6 @@
     <!-- Size of status line font in LockScreen. -->
     <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
 
-    <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
-    <dimen name="default_app_widget_padding_left">12dp</dimen>
-    <dimen name="default_app_widget_padding_top">4dp</dimen>
-    <dimen name="default_app_widget_padding_right">12dp</dimen>
-    <dimen name="default_app_widget_padding_bottom">20dp</dimen>
-
     <!-- Minimum width for an action button in the menu area of an action bar -->
     <dimen name="action_button_min_width">64dip</dimen>
 
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index 34c7ea3..fc336ae 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -50,6 +50,12 @@
     <dimen name="preference_screen_header_padding_side">0dip</dimen>
     <integer name="preference_screen_header_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
 
+    <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
+    <dimen name="default_app_widget_padding_left">12dp</dimen>
+    <dimen name="default_app_widget_padding_top">4dp</dimen>
+    <dimen name="default_app_widget_padding_right">12dp</dimen>
+    <dimen name="default_app_widget_padding_bottom">20dp</dimen>
+
     <!-- Preference fragment padding, sides -->
     <dimen name="preference_fragment_padding_side">32dp</dimen>
     <!-- Padding to the left of the preference panel breadcrumb -->
diff --git a/core/res/res/values-w500dp/bools.xml b/core/res/res/values-w500dp/bools.xml
deleted file mode 100644
index f53fd39..0000000
--- a/core/res/res/values-w500dp/bools.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<resources>
-    <bool name="activity_chooser_view_has_default_activity">true</bool>
-</resources>
\ No newline at end of file
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 6910ebe..f9762b1 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -22,5 +22,4 @@
     <bool name="show_ongoing_ime_switcher">true</bool>
     <bool name="action_bar_expanded_action_views_exclusive">true</bool>
     <bool name="target_honeycomb_needs_options_menu">true</bool>
-    <bool name="activity_chooser_view_has_default_activity">false</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 48038dd..a24e345c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1380,7 +1380,6 @@
   <java-symbol type="bool" name="config_wifi_dual_band_support" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
-  <java-symbol type="bool" name="activity_chooser_view_has_default_activity" />
   <java-symbol type="color" name="config_defaultNotificationColor" />
   <java-symbol type="drawable" name="ic_notification_ime_default" />
   <java-symbol type="drawable" name="stat_notify_car_mode" />
diff --git a/core/tests/utillib/src/android/test/BandwidthTestCase.java b/core/tests/utillib/src/android/test/BandwidthTestCase.java
index 4f95f77..c03d9b3 100644
--- a/core/tests/utillib/src/android/test/BandwidthTestCase.java
+++ b/core/tests/utillib/src/android/test/BandwidthTestCase.java
@@ -18,6 +18,7 @@
 import android.net.NetworkStats;
 import android.net.TrafficStats;
 import android.os.Bundle;
+import android.util.Log;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -29,6 +30,7 @@
  * as an {@link InstrumentationTestCase}
  */
 public class BandwidthTestCase extends InstrumentationTestCase {
+    private static final String TAG = "BandwidthTestCase";
     private static final String REPORT_KEY_PACKETS_SENT = "txPackets";
     private static final String REPORT_KEY_PACKETS_RECEIVED = "rxPackets";
     private static final String REPORT_KEY_BYTES_SENT = "txBytes";
@@ -86,11 +88,26 @@
             }
         } else if (method.isAnnotationPresent(BandwidthTest.class) ||
                 testClass.isAnnotationPresent(BandwidthTest.class)) {
-            TrafficStats.startDataProfiling(null);
+            /**
+             * If bandwidth profiling fails for whatever reason the test
+             * should be allow to execute to its completion.
+             * Typically bandwidth profiling would fail when a lower level
+             * component is missing, such as the kernel module, for a newly
+             * introduced hardware.
+             */
+            try{
+                TrafficStats.startDataProfiling(null);
+            } catch(IllegalStateException isx){
+                Log.w(TAG, "Failed to start bandwidth profiling");
+            }
             runMethod(method, 1, false);
-            NetworkStats stats = TrafficStats.stopDataProfiling(null);
-            NetworkStats.Entry entry = stats.getTotal(null);
-            getInstrumentation().sendStatus(2, getBandwidthStats(entry));
+            try{
+                NetworkStats stats = TrafficStats.stopDataProfiling(null);
+                NetworkStats.Entry entry = stats.getTotal(null);
+                getInstrumentation().sendStatus(2, getBandwidthStats(entry));
+            } catch (IllegalStateException isx){
+                Log.w(TAG, "Failed to collect bandwidth stats");
+            }
         } else {
             runMethod(method, runCount, isRepetitive);
         }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d2a6a7a..a5f653a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -162,6 +162,13 @@
     }
     mBitmapResources.clear();
 
+    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
+        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
+        caches.resourceCache.decrementRefcount(bitmap);
+        caches.resourceCache.destructor(bitmap);
+    }
+    mOwnedBitmapResources.clear();
+
     for (size_t i = 0; i < mFilterResources.size(); i++) {
         caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
     }
@@ -217,44 +224,51 @@
 
     Caches& caches = Caches::getInstance();
 
-    const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources();
+    const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
     for (size_t i = 0; i < bitmapResources.size(); i++) {
         SkBitmap* resource = bitmapResources.itemAt(i);
         mBitmapResources.add(resource);
         caches.resourceCache.incrementRefcount(resource);
     }
 
-    const Vector<SkiaColorFilter*> &filterResources = recorder.getFilterResources();
+    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
+    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
+        SkBitmap* resource = ownedBitmapResources.itemAt(i);
+        mOwnedBitmapResources.add(resource);
+        caches.resourceCache.incrementRefcount(resource);
+    }
+
+    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
     for (size_t i = 0; i < filterResources.size(); i++) {
         SkiaColorFilter* resource = filterResources.itemAt(i);
         mFilterResources.add(resource);
         caches.resourceCache.incrementRefcount(resource);
     }
 
-    const Vector<SkiaShader*> &shaders = recorder.getShaders();
+    const Vector<SkiaShader*>& shaders = recorder.getShaders();
     for (size_t i = 0; i < shaders.size(); i++) {
         SkiaShader* resource = shaders.itemAt(i);
         mShaders.add(resource);
         caches.resourceCache.incrementRefcount(resource);
     }
 
-    const Vector<SkPaint*> &paints = recorder.getPaints();
+    const Vector<SkPaint*>& paints = recorder.getPaints();
     for (size_t i = 0; i < paints.size(); i++) {
         mPaints.add(paints.itemAt(i));
     }
 
-    const Vector<SkPath*> &paths = recorder.getPaths();
+    const Vector<SkPath*>& paths = recorder.getPaths();
     for (size_t i = 0; i < paths.size(); i++) {
         mPaths.add(paths.itemAt(i));
     }
 
-    const SortedVector<SkPath*> &sourcePaths = recorder.getSourcePaths();
+    const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
     for (size_t i = 0; i < sourcePaths.size(); i++) {
         mSourcePaths.add(sourcePaths.itemAt(i));
         caches.resourceCache.incrementRefcount(sourcePaths.itemAt(i));
     }
 
-    const Vector<SkMatrix*> &matrices = recorder.getMatrices();
+    const Vector<SkMatrix*>& matrices = recorder.getMatrices();
     for (size_t i = 0; i < matrices.size(); i++) {
         mMatrices.add(matrices.itemAt(i));
     }
@@ -1036,10 +1050,7 @@
                 SkPaint* paint = getPaint(renderer);
                 DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
                         bitmap, x, y, paint);
-                if (bitmap) {
-                    renderer.drawBitmap(bitmap, x, y, paint);
-                    delete bitmap;
-                }
+                renderer.drawBitmap(bitmap, x, y, paint);
             }
             break;
             case DrawBitmapMesh: {
@@ -1295,6 +1306,12 @@
     }
     mBitmapResources.clear();
 
+    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
+        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
+        caches.resourceCache.decrementRefcount(bitmap);
+    }
+    mOwnedBitmapResources.clear();
+
     for (size_t i = 0; i < mFilterResources.size(); i++) {
         caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
     }
@@ -1336,6 +1353,10 @@
     return displayList;
 }
 
+bool DisplayListRenderer::isDeferred() {
+    return true;
+}
+
 void DisplayListRenderer::setViewport(int width, int height) {
     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 2f74f5b..93b065d 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -398,7 +398,6 @@
 
 private:
     void init();
-
     void initProperties();
 
     void clearResources();
@@ -424,16 +423,7 @@
     }
 
     SkBitmap* getBitmapData() {
-        SkBitmap* bitmap = new SkBitmap;
-        bitmap->setConfig((SkBitmap::Config) getInt(), getInt(), getInt());
-        if (!bitmap->allocPixels()) {
-            delete bitmap;
-            return NULL;
-        }
-
-        bitmap->setPixels((void*) mReader.skip(bitmap->height() * bitmap->rowBytes()));
-
-        return bitmap;
+        return (SkBitmap*) getInt();
     }
 
     SkiaShader* getShader() {
@@ -497,6 +487,7 @@
     }
 
     Vector<SkBitmap*> mBitmapResources;
+    Vector<SkBitmap*> mOwnedBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
@@ -552,6 +543,8 @@
 
     ANDROID_API DisplayList* getDisplayList(DisplayList* displayList);
 
+    virtual bool isDeferred();
+
     virtual void setViewport(int width, int height);
     virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
@@ -634,6 +627,10 @@
         return mBitmapResources;
     }
 
+    const Vector<SkBitmap*>& getOwnedBitmapResources() const {
+        return mOwnedBitmapResources;
+    }
+
     const Vector<SkiaColorFilter*>& getFilterResources() const {
         return mFilterResources;
     }
@@ -719,17 +716,6 @@
         mWriter.write(values, count * sizeof(int32_t));
     }
 
-    void addBitmapData(SkBitmap* bitmap) {
-        mWriter.writeInt(bitmap->config());
-        mWriter.writeInt(bitmap->width());
-        mWriter.writeInt(bitmap->height());
-
-        SkAutoLockPixels alp(*bitmap);
-        void* src = bitmap->getPixels();
-
-        mWriter.write(src, bitmap->rowBytes() * bitmap->height());
-    }
-
     void addUInts(const uint32_t* values, int8_t count) {
         mWriter.writeInt(count);
         mWriter.write(values, count * sizeof(uint32_t));
@@ -825,6 +811,12 @@
         Caches::getInstance().resourceCache.incrementRefcount(bitmap);
     }
 
+    void addBitmapData(SkBitmap* bitmap) {
+        addInt((int) bitmap);
+        mOwnedBitmapResources.add(bitmap);
+        Caches::getInstance().resourceCache.incrementRefcount(bitmap);
+    }
+
     inline void addShader(SkiaShader* shader) {
         if (!shader) {
             addInt((int) NULL);
@@ -851,6 +843,7 @@
     }
 
     Vector<SkBitmap*> mBitmapResources;
+    Vector<SkBitmap*> mOwnedBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7f242c3..50f5d57 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -144,6 +144,10 @@
     return STENCIL_BUFFER_SIZE;
 }
 
+bool OpenGLRenderer::isDeferred() {
+    return false;
+}
+
 void OpenGLRenderer::setViewport(int width, int height) {
     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0ea0db7..ab324ff 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -63,6 +63,8 @@
     ANDROID_API OpenGLRenderer();
     virtual ~OpenGLRenderer();
 
+    virtual bool isDeferred();
+
     virtual void setViewport(int width, int height);
 
     ANDROID_API void prepare(bool opaque);
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 9ffad88..cf5f822 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -59,11 +59,11 @@
 void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
     SkSafeRef(bitmapResource->pixelRef());
     SkSafeRef(bitmapResource->getColorTable());
-    incrementRefcount((void*)bitmapResource, kBitmap);
+    incrementRefcount((void*) bitmapResource, kBitmap);
 }
 
 void ResourceCache::incrementRefcount(SkPath* pathResource) {
-    incrementRefcount((void*)pathResource, kPath);
+    incrementRefcount((void*) pathResource, kPath);
 }
 
 void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index bc144bb..4cff67b 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -48,7 +48,7 @@
             android:id="@+id/latestItems"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            systemui:rowHeight="@dimen/notification_height"
+            systemui:rowHeight="@dimen/notification_row_min_height"
             />
     </ScrollView>
 
@@ -68,4 +68,4 @@
 
     </com.android.systemui.statusbar.phone.CloseDragHandle>
 
-</FrameLayout><!-- end of sliding panel -->
\ No newline at end of file
+</FrameLayout><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel.xml b/packages/SystemUI/res/layout/system_bar_notification_panel.xml
index 42af147..5579505 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel.xml
@@ -77,7 +77,7 @@
                     android:clickable="true"
                     android:focusable="true"
                     android:descendantFocusability="afterDescendants"
-                    systemui:rowHeight="@dimen/notification_height"
+                    systemui:rowHeight="@dimen/notification_row_min_height"
                     />
             </ScrollView>
         </LinearLayout>
diff --git a/packages/SystemUI/res/values-xhdpi/dimens.xml b/packages/SystemUI/res/values-xhdpi/dimens.xml
deleted file mode 100644
index 303841a..0000000
--- a/packages/SystemUI/res/values-xhdpi/dimens.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
--->
-<resources>
-    <!-- thickness (height) of each notification row, including any separators or padding -->
-    <!-- note: this is the same value as in values/dimens.xml; the value is overridden in
-         values-hdpi/dimens.xml and so we need to re-assert the general value here -->
-    <dimen name="notification_height">68dp</dimen>
-
-    <!-- thickness (height) of dividers between each notification row -->
-    <!-- same as in values/dimens.xml; see note at notification_height -->
-    <dimen name="notification_divider_height">2dp</dimen>
-</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f548166..9042045 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -49,18 +49,21 @@
          reducing false presses on navbar buttons; approx 2mm -->
     <dimen name="navigation_bar_deadzone_size">12dp</dimen>
 
-    <!-- thickness (height) of each 1U notification row plus glow, padding, etc -->
-    <dimen name="notification_height">72dp</dimen>
-
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
 
-    <!-- Height of a small notification in the status bar plus glow, padding, etc -->
-    <dimen name="notification_min_height">72dp</dimen>
+    <!-- Height of a small notification in the status bar -->
+    <dimen name="notification_min_height">64dp</dimen>
 
     <!-- Height of a large notification in the status bar -->
     <dimen name="notification_max_height">256dp</dimen>
 
+    <!-- Height of a small notification in the status bar plus glow, padding, etc -->
+    <dimen name="notification_row_min_height">72dp</dimen>
+
+    <!-- Height of a large notification in the status bar plus glow, padding, etc -->
+    <dimen name="notification_row_max_height">260dp</dimen>
+
     <!-- size at which Notification icons will be drawn in the status bar -->
     <dimen name="status_bar_icon_drawing_size">18dip</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 9e273d4..3502b62 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -41,7 +41,7 @@
  */
 public class RingtonePlayer extends SystemUI {
     private static final String TAG = "RingtonePlayer";
-    private static final boolean LOGD = true;
+    private static final boolean LOGD = false;
 
     // TODO: support Uri switching under same IBinder
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 71d26b5..4b223dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -478,7 +478,7 @@
 
     protected  boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
         int rowHeight =
-                mContext.getResources().getDimensionPixelSize(R.dimen.notification_height);
+                mContext.getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
         int minHeight =
                 mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height);
         int maxHeight =
@@ -498,7 +498,6 @@
         // for blaming (see SwipeHelper.setLongPressListener)
         row.setTag(sbn.pkg);
 
-        ViewGroup.LayoutParams lp = row.getLayoutParams();
         workAroundBadLayerDrawableOpacity(row);
         View vetoButton = updateNotificationVetoButton(row, sbn);
         vetoButton.setContentDescription(mContext.getString(
@@ -510,13 +509,6 @@
         ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
         ViewGroup adaptive = (ViewGroup)row.findViewById(R.id.adaptive);
 
-        // Ensure that R.id.content is properly set to 64dp high if 1U
-        lp = content.getLayoutParams();
-        if (large == null) {
-            lp.height = minHeight;
-        }
-        content.setLayoutParams(lp);
-
         content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
 
         PendingIntent contentIntent = sbn.notification.contentIntent;
@@ -528,6 +520,7 @@
             content.setOnClickListener(null);
         }
 
+        // TODO(cwren) normalize variable names with those in updateNotification
         View expandedOneU = null;
         View expandedLarge = null;
         Exception exception = null;
@@ -556,7 +549,7 @@
                 SizeAdaptiveLayout.LayoutParams params =
                         new SizeAdaptiveLayout.LayoutParams(expandedLarge.getLayoutParams());
                 params.minHeight = minHeight+1;
-                params.maxHeight = SizeAdaptiveLayout.LayoutParams.UNBOUNDED;
+                params.maxHeight = maxHeight;
                 adaptive.addView(expandedLarge, params);
             }
             row.setDrawingCacheEnabled(true);
@@ -723,20 +716,18 @@
     }
 
     protected boolean expandView(NotificationData.Entry entry, boolean expand) {
-        if (entry.expandable()) {
-            int rowHeight =
-                    mContext.getResources().getDimensionPixelSize(R.dimen.notification_height);
-            ViewGroup.LayoutParams lp = entry.row.getLayoutParams();
-            if (expand) {
-                lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
-            } else {
-                lp.height = rowHeight;
-            }
-            entry.row.setLayoutParams(lp);
-            return expand;
+        int rowHeight =
+                mContext.getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
+        ViewGroup.LayoutParams lp = entry.row.getLayoutParams();
+        if (entry.expandable() && expand) {
+            if (DEBUG) Slog.d(TAG, "setting expanded row height to WRAP_CONTENT");
+            lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
         } else {
-            return false;
+            if (DEBUG) Slog.d(TAG, "setting collapsed row height to " + rowHeight);
+            lp.height = rowHeight;
         }
+        entry.row.setLayoutParams(lp);
+        return expand;
     }
 
     protected void updateExpansionStates() {
@@ -781,32 +772,41 @@
         final StatusBarNotification oldNotification = oldEntry.notification;
 
         // XXX: modify when we do something more intelligent with the two content views
-        final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null)
-                ? oldNotification.notification.bigContentView
-                : oldNotification.notification.contentView;
-        final RemoteViews contentView = (notification.notification.bigContentView != null)
-                ? notification.notification.bigContentView
-                : notification.notification.contentView;
+        final RemoteViews oldContentView = oldNotification.notification.contentView;
+        final RemoteViews contentView = notification.notification.contentView;
+        final RemoteViews oldBigContentView = oldNotification.notification.bigContentView;
+        final RemoteViews bigContentView = notification.notification.bigContentView;
 
         if (DEBUG) {
             Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
                     + " ongoing=" + oldNotification.isOngoing()
                     + " expanded=" + oldEntry.expanded
                     + " contentView=" + oldContentView
+                    + " bigContentView=" + oldBigContentView
                     + " rowParent=" + oldEntry.row.getParent());
             Slog.d(TAG, "new notification: when=" + notification.notification.when
                     + " ongoing=" + oldNotification.isOngoing()
-                    + " contentView=" + contentView);
+                    + " contentView=" + contentView
+                    + " bigContentView=" + bigContentView);
         }
 
         // Can we just reapply the RemoteViews in place?  If when didn't change, the order
         // didn't change.
+
+        // 1U is never null
         boolean contentsUnchanged = oldEntry.expanded != null
-                && contentView != null && oldContentView != null
                 && contentView.getPackage() != null
                 && oldContentView.getPackage() != null
                 && oldContentView.getPackage().equals(contentView.getPackage())
                 && oldContentView.getLayoutId() == contentView.getLayoutId();
+        // large view may be null
+        boolean bigContentsUnchanged =
+                (oldEntry.getLargeView() == null && bigContentView == null)
+                || ((oldEntry.getLargeView() != null && bigContentView != null)
+                    && bigContentView.getPackage() != null
+                    && oldBigContentView.getPackage() != null
+                    && oldBigContentView.getPackage().equals(bigContentView.getPackage())
+                    && oldBigContentView.getLayoutId() == bigContentView.getLayoutId());
         ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
         boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
                 && notification.score == oldNotification.score;
@@ -816,12 +816,15 @@
                 && !TextUtils.equals(notification.notification.tickerText,
                         oldEntry.notification.notification.tickerText);
         boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
-        if (contentsUnchanged && (orderUnchanged || isTopAnyway)) {
+        if (contentsUnchanged && bigContentsUnchanged && (orderUnchanged || isTopAnyway)) {
             if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
             oldEntry.notification = notification;
             try {
                 // Reapply the RemoteViews
-                contentView.reapply(mContext, oldEntry.content);
+                contentView.reapply(mContext, oldEntry.expanded);
+                if (bigContentView != null && oldEntry.getLargeView() != null) {
+                    bigContentView.reapply(mContext, oldEntry.getLargeView());
+                }
                 // update the contentIntent
                 final PendingIntent contentIntent = notification.notification.contentIntent;
                 if (contentIntent != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 0fe7a0a..f41d99c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -101,8 +101,8 @@
         float densityScale = getResources().getDisplayMetrics().density;
         float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
         mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
-        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
-        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
+        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
+        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(mContext, this, minHeight, maxHeight);
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 06cd69e..203f9db 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -113,10 +113,7 @@
         mPasswordEntry.setOnEditorActionListener(this);
 
         mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
-        mKeyboardHelper.setEnableHaptics(
-                Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, 0)
-                        != 0);
+        mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
         boolean imeOrDeleteButtonVisible = false;
         if (mIsAlpha) {
             // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 889fbe4..3fbac38 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -20,6 +20,7 @@
 import com.android.server.input.InputFilter;
 
 import android.content.Context;
+import android.os.PowerManager;
 import android.util.Slog;
 import android.view.InputDevice;
 import android.view.InputEvent;
@@ -37,6 +38,8 @@
 
     private final Context mContext;
 
+    private final PowerManager mPm;
+
     private final GestureListener mGestureListener;
 
     /**
@@ -74,6 +77,7 @@
         super(context.getMainLooper());
         mContext = context;
         mGestureListener = gestureListener;
+        mPm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
     }
 
     @Override
@@ -108,6 +112,7 @@
                 mTouchExplorer.clear(motionEvent, policyFlags);
             }
             if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) != 0) {
+                mPm.userActivity(event.getEventTime(), false);
                 mTouchExplorer.onMotionEvent(motionEvent, policyFlags);
             } else {
                 mTouchExplorer.clear(motionEvent, policyFlags);
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 28ce1df..1937bad 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -25,6 +25,7 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.app.PendingIntent;
+import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -1343,7 +1344,7 @@
                     sendDownAndUpKeyEvents(KeyEvent.KEYCODE_APP_SWITCH);
                 } return true;
                 case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
-                    // TODO: Implement when 6346026 is fixed.
+                    expandStatusBar();
                 } return true;
             }
             return false;
@@ -1413,6 +1414,16 @@
             Binder.restoreCallingIdentity(token);
         }
 
+        private void expandStatusBar() {
+            final long token = Binder.clearCallingIdentity();
+
+            StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
+                    android.app.Service.STATUS_BAR_SERVICE);
+            statusBarManager.expand();
+
+            Binder.restoreCallingIdentity(token);
+        }
+
         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b9f63cf..e6f4d918 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2619,6 +2619,7 @@
         }
 
         boolean addingToTask = false;
+        boolean movedHome = false;
         TaskRecord reuseTask = null;
         if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
@@ -2657,6 +2658,7 @@
                         if (callerAtFront) {
                             // We really do want to push this one into the
                             // user's face, right now.
+                            movedHome = true;
                             moveHomeToFrontFromLaunchLocked(launchFlags);
                             moveTaskToFrontLocked(taskTop.task, r, options);
                         }
@@ -2835,7 +2837,9 @@
                 r.setTask(reuseTask, reuseTask, true);
             }
             newTask = true;
-            moveHomeToFrontFromLaunchLocked(launchFlags);
+            if (!movedHome) {
+                moveHomeToFrontFromLaunchLocked(launchFlags);
+            }
             
         } else if (sourceRecord != null) {
             if (!addingToTask &&
@@ -3543,7 +3547,7 @@
         }
         ActivityRecord r = mHistory.get(index);
 
-        while (index > 0) {
+        while (index >= 0) {
             ActivityRecord cur = mHistory.get(index);
             if (cur.task != r.task) {
                 break;