Merge "Rename and repurpose feature MANAGED_PROFILES to MANAGED_USERS" into lmp-dev
diff --git a/core/java/android/animation/PathKeyframes.java b/core/java/android/animation/PathKeyframes.java
index 70eed90..2a47b68 100644
--- a/core/java/android/animation/PathKeyframes.java
+++ b/core/java/android/animation/PathKeyframes.java
@@ -17,7 +17,6 @@
 
 import android.graphics.Path;
 import android.graphics.PointF;
-import android.util.MathUtils;
 
 import java.util.ArrayList;
 
@@ -64,11 +63,12 @@
 
     @Override
     public Object getValue(float fraction) {
-        fraction = MathUtils.constrain(fraction, 0, 1);
-
         int numPoints = mKeyframeData.length / 3;
-
-        if (fraction == 0) {
+        if (fraction < 0) {
+            return interpolateInRange(fraction, 0, 1);
+        } else if (fraction > 1) {
+            return interpolateInRange(fraction, numPoints - 2, numPoints - 1);
+        } else if (fraction == 0) {
             return pointForIndex(0);
         } else if (fraction == 1) {
             return pointForIndex(numPoints - 1);
@@ -91,27 +91,31 @@
             }
 
             // now high is below the fraction and low is above the fraction
-            int startBase = (high * NUM_COMPONENTS);
-            int endBase = (low * NUM_COMPONENTS);
-
-            float startFraction = mKeyframeData[startBase + FRACTION_OFFSET];
-            float endFraction = mKeyframeData[endBase + FRACTION_OFFSET];
-
-            float intervalFraction = (fraction - startFraction)/(endFraction - startFraction);
-
-            float startX = mKeyframeData[startBase + X_OFFSET];
-            float endX = mKeyframeData[endBase + X_OFFSET];
-            float startY = mKeyframeData[startBase + Y_OFFSET];
-            float endY = mKeyframeData[endBase + Y_OFFSET];
-
-            float x = interpolate(intervalFraction, startX, endX);
-            float y = interpolate(intervalFraction, startY, endY);
-
-            mTempPointF.set(x, y);
-            return mTempPointF;
+            return interpolateInRange(fraction, high, low);
         }
     }
 
+    private PointF interpolateInRange(float fraction, int startIndex, int endIndex) {
+        int startBase = (startIndex * NUM_COMPONENTS);
+        int endBase = (endIndex * NUM_COMPONENTS);
+
+        float startFraction = mKeyframeData[startBase + FRACTION_OFFSET];
+        float endFraction = mKeyframeData[endBase + FRACTION_OFFSET];
+
+        float intervalFraction = (fraction - startFraction)/(endFraction - startFraction);
+
+        float startX = mKeyframeData[startBase + X_OFFSET];
+        float endX = mKeyframeData[endBase + X_OFFSET];
+        float startY = mKeyframeData[startBase + Y_OFFSET];
+        float endY = mKeyframeData[endBase + Y_OFFSET];
+
+        float x = interpolate(intervalFraction, startX, endX);
+        float y = interpolate(intervalFraction, startY, endY);
+
+        mTempPointF.set(x, y);
+        return mTempPointF;
+    }
+
     @Override
     public void invalidateCache() {
     }
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 43fa3f0..d02d17f 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -223,7 +223,10 @@
         mSharedElementNames.addAll(sharedElements.keySet());
         mSharedElements.addAll(sharedElements.values());
         if (getViewsTransition() != null) {
-            getDecor().captureTransitioningViews(mTransitioningViews);
+            ViewGroup decorView = getDecor();
+            if (decorView != null) {
+                decorView.captureTransitioningViews(mTransitioningViews);
+            }
             mTransitioningViews.removeAll(mSharedElements);
         }
         setEpicenter();
@@ -235,6 +238,7 @@
             View view = mTransitioningViews.get(i);
             if (!view.getGlobalVisibleRect(r)) {
                 mTransitioningViews.remove(i);
+                showView(view, true);
             }
         }
     }
@@ -350,7 +354,10 @@
                 sharedElements.put(accepted.get(i), localViews.get(i));
             }
         } else {
-            getDecor().findNamedViews(sharedElements);
+            ViewGroup decorView = getDecor();
+            if (decorView != null) {
+                decorView.findNamedViews(sharedElements);
+            }
         }
         return sharedElements;
     }
@@ -471,16 +478,18 @@
 
     protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
         final View decorView = getDecor();
-        decorView.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        notifySharedElementEnd(snapshots);
-                        return true;
+        if (decorView != null) {
+            decorView.getViewTreeObserver().addOnPreDrawListener(
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+                            notifySharedElementEnd(snapshots);
+                            return true;
+                        }
                     }
-                }
-        );
+            );
+        }
     }
 
     private static SharedElementOriginalState getOldSharedElementState(View view, String name,
@@ -523,7 +532,10 @@
         ArrayList<View> snapshots = new ArrayList<View>(numSharedElements);
         Context context = getWindow().getContext();
         int[] decorLoc = new int[2];
-        getDecor().getLocationOnScreen(decorLoc);
+        ViewGroup decorView = getDecor();
+        if (decorView != null) {
+            decorView.getLocationOnScreen(decorLoc);
+        }
         for (String name: names) {
             Bundle sharedElementBundle = state.getBundle(name);
             if (sharedElementBundle != null) {
@@ -605,14 +617,17 @@
     protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) {
         int count = views.size();
         for (int i = 0; i < count; i++) {
-            View view = views.get(i);
-            Float alpha = mOriginalAlphas.remove(view);
-            if (alpha != null) {
-                view.setAlpha(alpha);
-            }
-            if (setTransitionAlpha) {
-                view.setTransitionAlpha(1f);
-            }
+            showView(views.get(i), setTransitionAlpha);
+        }
+    }
+
+    private void showView(View view, boolean setTransitionAlpha) {
+        Float alpha = mOriginalAlphas.remove(view);
+        if (alpha != null) {
+            view.setAlpha(alpha);
+        }
+        if (setTransitionAlpha) {
+            view.setTransitionAlpha(1f);
         }
     }
 
@@ -746,15 +761,17 @@
 
     protected void scheduleGhostVisibilityChange(final int visibility) {
         final View decorView = getDecor();
-        decorView.getViewTreeObserver()
-                .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        setGhostVisibility(visibility);
-                        return true;
-                    }
-                });
+        if (decorView != null) {
+            decorView.getViewTreeObserver()
+                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+                            setGhostVisibility(visibility);
+                            return true;
+                        }
+                    });
+        }
     }
 
     protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter {
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 9ca150d..bfdb0eb 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -70,16 +70,18 @@
         resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this);
         mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
         final View decorView = getDecor();
-        decorView.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        if (mIsReadyForTransition) {
-                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+        if (decorView != null) {
+            decorView.getViewTreeObserver().addOnPreDrawListener(
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            if (mIsReadyForTransition) {
+                                decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+                            }
+                            return mIsReadyForTransition;
                         }
-                        return mIsReadyForTransition;
-                    }
-                });
+                    });
+        }
     }
 
     public void viewInstancesReady(ArrayList<String> accepted, ArrayList<String> localNames,
@@ -152,7 +154,10 @@
     private ArrayMap<String, View> mapNamedElements(ArrayList<String> accepted,
             ArrayList<String> localNames) {
         ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
-        getDecor().findNamedViews(sharedElements);
+        ViewGroup decorView = getDecor();
+        if (decorView != null) {
+            decorView.findNamedViews(sharedElements);
+        }
         if (accepted != null) {
             for (int i = 0; i < localNames.size(); i++) {
                 String localName = localNames.get(i);
@@ -170,10 +175,13 @@
 
     private void sendSharedElementDestination() {
         boolean allReady;
+        final View decorView = getDecor();
         if (allowOverlappingTransitions() && getEnterViewsTransition() != null) {
             allReady = false;
+        } else if (decorView == null) {
+            allReady = true;
         } else {
-            allReady = !getDecor().isLayoutRequested();
+            allReady = !decorView.isLayoutRequested();
             if (allReady) {
                 for (int i = 0; i < mSharedElements.size(); i++) {
                     if (mSharedElements.get(i).isLayoutRequested()) {
@@ -188,8 +196,7 @@
             setSharedElementMatrices();
             moveSharedElementsToOverlay();
             mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
-        } else {
-            final View decorView = getDecor();
+        } else if (decorView != null) {
             decorView.getViewTreeObserver()
                     .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                         @Override
@@ -291,6 +298,10 @@
     }
 
     private void startSharedElementTransition(Bundle sharedElementState) {
+        ViewGroup decorView = getDecor();
+        if (decorView == null) {
+            return;
+        }
         // Remove rejected shared elements
         ArrayList<String> rejectedNames = new ArrayList<String>(mAllSharedElementNames);
         rejectedNames.removeAll(mSharedElementNames);
@@ -311,7 +322,8 @@
         boolean startSharedElementTransition = true;
         setGhostVisibility(View.INVISIBLE);
         scheduleGhostVisibilityChange(View.INVISIBLE);
-        Transition transition = beginTransition(startEnterTransition, startSharedElementTransition);
+        Transition transition = beginTransition(decorView, startEnterTransition,
+                startSharedElementTransition);
         scheduleGhostVisibilityChange(View.VISIBLE);
         setGhostVisibility(View.VISIBLE);
 
@@ -324,8 +336,9 @@
         if (mResultReceiver != null) {
             // We can't trust that the view will disappear on the same frame that the shared
             // element appears here. Assure that we get at least 2 frames for double-buffering.
-            getDecor().postOnAnimation(new Runnable() {
+            decorView.postOnAnimation(new Runnable() {
                 int mAnimations;
+
                 @Override
                 public void run() {
                     if (mAnimations++ < MIN_ANIMATION_FRAMES) {
@@ -349,21 +362,23 @@
         final Bundle sharedElementState = mSharedElementsBundle;
         mSharedElementsBundle = null;
         final View decorView = getDecor();
-        decorView.getViewTreeObserver()
-                .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        startTransition(new Runnable() {
-                            @Override
-                            public void run() {
-                                startSharedElementTransition(sharedElementState);
-                            }
-                        });
-                        return false;
-                    }
-                });
-        decorView.invalidate();
+        if (decorView != null) {
+            decorView.getViewTreeObserver()
+                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+                            startTransition(new Runnable() {
+                                @Override
+                                public void run() {
+                                    startSharedElementTransition(sharedElementState);
+                                }
+                            });
+                            return false;
+                        }
+                    });
+            decorView.invalidate();
+        }
     }
 
     private void requestLayoutForSharedElements() {
@@ -373,7 +388,7 @@
         }
     }
 
-    private Transition beginTransition(boolean startEnterTransition,
+    private Transition beginTransition(ViewGroup decorView, boolean startEnterTransition,
             boolean startSharedElementTransition) {
         Transition sharedElementTransition = null;
         if (startSharedElementTransition) {
@@ -433,7 +448,7 @@
         Transition transition = mergeTransitions(sharedElementTransition, viewsTransition);
         if (transition != null) {
             transition.addListener(new ContinueTransitionListener());
-            TransitionManager.beginDelayedTransition(getDecor(), transition);
+            TransitionManager.beginDelayedTransition(decorView, transition);
             if (startSharedElementTransition && !mSharedElementNames.isEmpty()) {
                 mSharedElements.get(0).invalidate();
             } else if (startEnterTransition && !mTransitioningViews.isEmpty()) {
@@ -467,8 +482,9 @@
     }
 
     private void startEnterTransition(Transition transition) {
-        if (!mIsReturning) {
-            Drawable background = getDecor().getBackground();
+        ViewGroup decorView = getDecor();
+        if (!mIsReturning && decorView != null) {
+            Drawable background = decorView.getBackground();
             if (background != null) {
                 background = background.mutate();
                 getWindow().setBackgroundDrawable(background);
@@ -539,25 +555,28 @@
         if (rejectedSnapshots == null || rejectedSnapshots.isEmpty()) {
             return;
         }
-        ViewGroupOverlay overlay = getDecor().getOverlay();
-        ObjectAnimator animator = null;
-        int numRejected = rejectedSnapshots.size();
-        for (int i = 0; i < numRejected; i++) {
-            View snapshot = rejectedSnapshots.get(i);
-            overlay.add(snapshot);
-            animator = ObjectAnimator.ofFloat(snapshot, View.ALPHA, 1, 0);
-            animator.start();
-        }
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                ViewGroupOverlay overlay = getDecor().getOverlay();
-                int numRejected = rejectedSnapshots.size();
-                for (int i = 0; i < numRejected; i++) {
-                    overlay.remove(rejectedSnapshots.get(i));
-                }
+        final ViewGroup decorView = getDecor();
+        if (decorView != null) {
+            ViewGroupOverlay overlay = decorView.getOverlay();
+            ObjectAnimator animator = null;
+            int numRejected = rejectedSnapshots.size();
+            for (int i = 0; i < numRejected; i++) {
+                View snapshot = rejectedSnapshots.get(i);
+                overlay.add(snapshot);
+                animator = ObjectAnimator.ofFloat(snapshot, View.ALPHA, 1, 0);
+                animator.start();
             }
-        });
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    ViewGroupOverlay overlay = decorView.getOverlay();
+                    int numRejected = rejectedSnapshots.size();
+                    for (int i = 0; i < numRejected; i++) {
+                        overlay.remove(rejectedSnapshots.get(i));
+                    }
+                }
+            });
+        }
     }
 
     protected void onRemoteExitTransitionComplete() {
@@ -572,9 +591,12 @@
             public void run() {
                 boolean startEnterTransition = true;
                 boolean startSharedElementTransition = false;
-                Transition transition = beginTransition(startEnterTransition,
-                        startSharedElementTransition);
-                startEnterTransition(transition);
+                ViewGroup decorView = getDecor();
+                if (decorView != null) {
+                    Transition transition = beginTransition(decorView, startEnterTransition,
+                            startSharedElementTransition);
+                    startEnterTransition(transition);
+                }
             }
         });
     }
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index e85ec63..41b0db6 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -129,22 +129,25 @@
         showViews(mTransitioningViews, true);
         showViews(mSharedElements, true);
         mIsHidden = true;
-        if (!mIsReturning && getDecor() != null) {
-            getDecor().suppressLayout(false);
+        ViewGroup decorView = getDecor();
+        if (!mIsReturning && decorView != null) {
+            decorView.suppressLayout(false);
         }
         moveSharedElementsFromOverlay();
         clearState();
     }
 
     private void sharedElementExitBack() {
-        if (getDecor() != null) {
-            getDecor().suppressLayout(true);
+        final ViewGroup decorView = getDecor();
+        if (decorView != null) {
+            decorView.suppressLayout(true);
         }
-        if (mExitSharedElementBundle != null && !mExitSharedElementBundle.isEmpty() &&
+        if (decorView != null && mExitSharedElementBundle != null &&
+                !mExitSharedElementBundle.isEmpty() &&
                 !mSharedElements.isEmpty() && getSharedElementTransition() != null) {
             startTransition(new Runnable() {
                 public void run() {
-                    startSharedElementExit();
+                    startSharedElementExit(decorView);
                 }
             });
         } else {
@@ -152,7 +155,7 @@
         }
     }
 
-    private void startSharedElementExit() {
+    private void startSharedElementExit(final ViewGroup decorView) {
         Transition transition = getSharedElementExitTransition();
         transition.addListener(new Transition.TransitionListenerAdapter() {
             @Override
@@ -165,7 +168,6 @@
         });
         final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle,
                 mSharedElementNames);
-        final View decorView = getDecor();
         decorView.getViewTreeObserver()
                 .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                     @Override
@@ -178,10 +180,10 @@
         setGhostVisibility(View.INVISIBLE);
         scheduleGhostVisibilityChange(View.INVISIBLE);
         mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
-        TransitionManager.beginDelayedTransition(getDecor(), transition);
+        TransitionManager.beginDelayedTransition(decorView, transition);
         scheduleGhostVisibilityChange(View.VISIBLE);
         setGhostVisibility(View.VISIBLE);
-        getDecor().invalidate();
+        decorView.invalidate();
     }
 
     private void hideSharedElements() {
@@ -196,8 +198,9 @@
     public void startExit() {
         if (!mIsExitStarted) {
             mIsExitStarted = true;
-            if (getDecor() != null) {
-                getDecor().suppressLayout(true);
+            ViewGroup decorView = getDecor();
+            if (decorView != null) {
+                decorView.suppressLayout(true);
             }
             moveSharedElementsToOverlay();
             startTransition(new Runnable() {
@@ -212,8 +215,9 @@
     public void startExit(int resultCode, Intent data) {
         if (!mIsExitStarted) {
             mIsExitStarted = true;
-            if (getDecor() != null) {
-                getDecor().suppressLayout(true);
+            ViewGroup decorView = getDecor();
+            if (decorView != null) {
+                decorView.suppressLayout(true);
             }
             mHandler = new Handler() {
                 @Override
@@ -224,7 +228,7 @@
             };
             delayCancel();
             moveSharedElementsToOverlay();
-            if (getDecor().getBackground() == null) {
+            if (decorView != null && decorView.getBackground() == null) {
                 getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK));
             }
             ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, this,
@@ -248,8 +252,9 @@
 
     private void startExitTransition() {
         Transition transition = getExitTransition();
-        if (transition != null) {
-            TransitionManager.beginDelayedTransition(getDecor(), transition);
+        ViewGroup decorView = getDecor();
+        if (transition != null && decorView != null) {
+            TransitionManager.beginDelayedTransition(decorView, transition);
             mTransitioningViews.get(0).invalidate();
         } else {
             transitionStarted();
@@ -337,13 +342,14 @@
         Transition viewsTransition = getExitTransition();
 
         Transition transition = mergeTransitions(sharedElementTransition, viewsTransition);
-        if (transition != null) {
+        ViewGroup decorView = getDecor();
+        if (transition != null && decorView != null) {
             setGhostVisibility(View.INVISIBLE);
             scheduleGhostVisibilityChange(View.INVISIBLE);
-            TransitionManager.beginDelayedTransition(getDecor(), transition);
+            TransitionManager.beginDelayedTransition(decorView, transition);
             scheduleGhostVisibilityChange(View.VISIBLE);
             setGhostVisibility(View.VISIBLE);
-            getDecor().invalidate();
+            decorView.invalidate();
         } else {
             transitionStarted();
         }
@@ -392,8 +398,9 @@
                 mExitNotified = true;
                 mResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null);
                 mResultReceiver = null; // done talking
-                if (!mIsReturning && getDecor() != null) {
-                    getDecor().suppressLayout(false);
+                ViewGroup decorView = getDecor();
+                if (!mIsReturning && decorView != null) {
+                    decorView.suppressLayout(false);
                 }
                 finishIfNecessary();
             }
diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java
index 481d67a..398a7e9 100644
--- a/core/java/android/hardware/camera2/params/TonemapCurve.java
+++ b/core/java/android/hardware/camera2/params/TonemapCurve.java
@@ -81,7 +81,8 @@
      * <p>Values are stored as a contiguous array of {@code (Pin, Pout)} points.</p>
      *
      * <p>All parameters may have independent length but should have at most
-     * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements.</p>
+     * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements and
+     * at least 2 * {@value #POINT_SIZE} elements.</p>
      *
      * <p>All sub-elements must be in the inclusive range of
      * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
@@ -110,6 +111,10 @@
         checkArgumentArrayLengthDivisibleBy(green, POINT_SIZE, "green");
         checkArgumentArrayLengthDivisibleBy(blue, POINT_SIZE, "blue");
 
+        checkArgumentArrayLengthNoLessThan(red, MIN_CURVE_LENGTH, "red");
+        checkArgumentArrayLengthNoLessThan(green, MIN_CURVE_LENGTH, "green");
+        checkArgumentArrayLengthNoLessThan(blue, MIN_CURVE_LENGTH, "blue");
+
         checkArrayElementsInRange(red, LEVEL_BLACK, LEVEL_WHITE, "red");
         checkArrayElementsInRange(green, LEVEL_BLACK, LEVEL_WHITE, "green");
         checkArrayElementsInRange(blue, LEVEL_BLACK, LEVEL_WHITE, "blue");
@@ -140,6 +145,14 @@
         return colorChannel;
     }
 
+    private static void checkArgumentArrayLengthNoLessThan(float[] array, int minLength,
+            String arrayName) {
+        if (array.length < minLength) {
+            throw new IllegalArgumentException(arrayName + " size must be at least "
+                    + minLength);
+        }
+    }
+
     /**
      * Get the number of points stored in this tonemap curve for the specified color channel.
      *
@@ -270,6 +283,47 @@
         return mHashCode;
     }
 
+    /**
+     * Return the TonemapCurve as a string representation.
+     *
+     * <p> {@code "TonemapCurve{R:[(%f, %f), (%f, %f) ... (%f, %f)], G:[(%f, %f), (%f, %f) ...
+     * (%f, %f)], B:[(%f, %f), (%f, %f) ... (%f, %f)]}"},
+     * where each {@code (%f, %f)} respectively represents one point of the corresponding
+     * tonemap curve. </p>
+     *
+     * @return string representation of {@link TonemapCurve}
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("TonemapCurve{");
+        sb.append("R:");
+        sb.append(curveToString(CHANNEL_RED));
+        sb.append(", G:");
+        sb.append(curveToString(CHANNEL_GREEN));
+        sb.append(", B:");
+        sb.append(curveToString(CHANNEL_BLUE));
+        sb.append("}");
+        return sb.toString();
+    }
+
+    private String curveToString(int colorChannel) {
+        checkArgumentColorChannel(colorChannel);
+        StringBuilder sb = new StringBuilder("[");
+        float[] curve = getCurve(colorChannel);
+        int pointCount = curve.length / POINT_SIZE;
+        for (int i = 0, j = 0; i < pointCount; i++, j += 2) {
+            sb.append("(");
+            sb.append(curve[j]);
+            sb.append(", ");
+            sb.append(curve[j+1]);
+            sb.append("), ");
+        }
+        // trim extra ", " at the end. Guaranteed to work because pointCount >= 2
+        sb.setLength(sb.length() - 2);
+        sb.append("]");
+        return sb.toString();
+    }
+
     private float[] getCurve(int colorChannel) {
         switch (colorChannel) {
             case CHANNEL_RED:
@@ -285,6 +339,8 @@
 
     private final static int OFFSET_POINT_IN = 0;
     private final static int OFFSET_POINT_OUT = 1;
+    private final static int TONEMAP_MIN_CURVE_POINTS = 2;
+    private final static int MIN_CURVE_LENGTH = TONEMAP_MIN_CURVE_POINTS * POINT_SIZE;
 
     private final float[] mRed;
     private final float[] mGreen;
@@ -292,4 +348,4 @@
 
     private int mHashCode;
     private boolean mHashCalculated = false;
-};
+}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index d1ad0ad..5230128 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -236,6 +236,7 @@
     private static final int EX_NULL_POINTER = -4;
     private static final int EX_ILLEGAL_STATE = -5;
     private static final int EX_NETWORK_MAIN_THREAD = -6;
+    private static final int EX_UNSUPPORTED_OPERATION = -7;
     private static final int EX_HAS_REPLY_HEADER = -128;  // special; see below
 
     private static native int nativeDataSize(long nativePtr);
@@ -1427,6 +1428,8 @@
             code = EX_ILLEGAL_STATE;
         } else if (e instanceof NetworkOnMainThreadException) {
             code = EX_NETWORK_MAIN_THREAD;
+        } else if (e instanceof UnsupportedOperationException) {
+            code = EX_UNSUPPORTED_OPERATION;
         }
         writeInt(code);
         StrictMode.clearGatheredViolations();
@@ -1545,6 +1548,8 @@
                 throw new IllegalStateException(msg);
             case EX_NETWORK_MAIN_THREAD:
                 throw new NetworkOnMainThreadException();
+            case EX_UNSUPPORTED_OPERATION:
+                throw new UnsupportedOperationException(msg);
         }
         throw new RuntimeException("Unknown exception code: " + code
                 + " msg " + msg);
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 40bb6ec..b677888 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -690,11 +690,18 @@
         for (int i = 0; i < startValuesListCount; ++i) {
             TransitionValues start = startValuesList.get(i);
             TransitionValues end = endValuesList.get(i);
-            // Only bother trying to animate with valid values that differ between start/end
-            boolean isInvalidStart = start != null && !isValidTarget(start.view);
-            boolean isInvalidEnd = end != null && !isValidTarget(end.view);
-            boolean isChanged = start != end && (start == null || !start.equals(end));
-            if (isChanged && !isInvalidStart && !isInvalidEnd) {
+            if (start != null && !start.targetedTransitions.contains(this)) {
+                start = null;
+            }
+            if (end != null && !end.targetedTransitions.contains(this)) {
+                end = null;
+            }
+            if (start == null && end == null) {
+                continue;
+            }
+            // Only bother trying to animate with values that differ between start/end
+            boolean isChanged = start == null || end == null || areValuesChanged(start, end);
+            if (isChanged) {
                 if (DBG) {
                     View view = (end != null) ? end.view : start.view;
                     Log.d(LOG_TAG, "  differing start/end values for view " + view);
@@ -1415,11 +1422,12 @@
                     } else {
                         captureEndValues(values);
                     }
+                    values.targetedTransitions.add(this);
                     capturePropagationValues(values);
                     if (start) {
-                        addViewValues(mStartValues, view, values, true);
+                        addViewValues(mStartValues, view, values);
                     } else {
-                        addViewValues(mEndValues, view, values, true);
+                        addViewValues(mEndValues, view, values);
                     }
                 }
             }
@@ -1432,6 +1440,7 @@
                 } else {
                     captureEndValues(values);
                 }
+                values.targetedTransitions.add(this);
                 capturePropagationValues(values);
                 if (start) {
                     mStartValues.viewValues.put(view, values);
@@ -1460,7 +1469,7 @@
     }
 
     static void addViewValues(TransitionValuesMaps transitionValuesMaps,
-            View view, TransitionValues transitionValues, boolean setTransientState) {
+            View view, TransitionValues transitionValues) {
         transitionValuesMaps.viewValues.put(view, transitionValues);
         int id = view.getId();
         if (id >= 0) {
@@ -1489,15 +1498,11 @@
                     // Duplicate item IDs: cannot match by item ID.
                     View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId);
                     if (alreadyMatched != null) {
-                        if (setTransientState) {
-                            alreadyMatched.setHasTransientState(false);
-                        }
+                        alreadyMatched.setHasTransientState(false);
                         transitionValuesMaps.itemIdValues.put(itemId, null);
                     }
                 } else {
-                    if (setTransientState) {
-                        view.setHasTransientState(true);
-                    }
+                    view.setHasTransientState(true);
                     transitionValuesMaps.itemIdValues.put(itemId, view);
                 }
             }
@@ -1562,11 +1567,12 @@
             } else {
                 captureEndValues(values);
             }
+            values.targetedTransitions.add(this);
             capturePropagationValues(values);
             if (start) {
-                addViewValues(mStartValues, view, values, true);
+                addViewValues(mStartValues, view, values);
             } else {
-                addViewValues(mEndValues, view, values, true);
+                addViewValues(mEndValues, view, values);
             }
         }
         if (view instanceof ViewGroup) {
@@ -1731,8 +1737,10 @@
                 if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
                     TransitionValues oldValues = oldInfo.values;
                     View oldView = oldInfo.view;
-                    TransitionValues newValues = getMatchedTransitionValues(oldView, true);
-                    boolean cancel = oldInfo.transition.areValuesChanged(oldValues, newValues);
+                    TransitionValues startValues = getTransitionValues(oldView, true);
+                    TransitionValues endValues = getMatchedTransitionValues(oldView, true);
+                    boolean cancel = (startValues != null || endValues != null) &&
+                            oldInfo.transition.areValuesChanged(oldValues, endValues);
                     if (cancel) {
                         if (anim.isRunning() || anim.isStarted()) {
                             if (DBG) {
@@ -1784,7 +1792,17 @@
             String key) {
         Object oldValue = oldValues.values.get(key);
         Object newValue = newValues.values.get(key);
-        boolean changed = (oldValue != null && newValue != null && !oldValue.equals(newValue));
+        boolean changed;
+        if (oldValue == null && newValue == null) {
+            // both are null
+            changed = false;
+        } else if (oldValue == null || newValue == null) {
+            // one is null
+            changed = true;
+        } else {
+            // neither is null
+            changed = !oldValue.equals(newValue);
+        }
         if (DBG && changed) {
             Log.d(LOG_TAG, "Transition.playTransition: " +
                     "oldValue != newValue for " + key +
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 669621eb3..09d2c69 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -388,8 +388,6 @@
     protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
             TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
             ArrayList<TransitionValues> endValuesList) {
-        startValues = removeExcludes(startValues);
-        endValues = removeExcludes(endValues);
         long startDelay = getStartDelay();
         int numTransitions = mTransitions.size();
         for (int i = 0; i < numTransitions; i++) {
@@ -409,24 +407,6 @@
         }
     }
 
-    private TransitionValuesMaps removeExcludes(TransitionValuesMaps values) {
-        if (mTargetIds.isEmpty() && mTargetIdExcludes == null && mTargetTypeExcludes == null
-                && mTargetNames == null && mTargetTypes == null
-                && mTargetExcludes == null && mTargetNameExcludes == null
-                && mTargets.isEmpty()) {
-            return values;
-        }
-        TransitionValuesMaps included = new TransitionValuesMaps();
-        int numValues = values.viewValues.size();
-        for (int i = 0; i < numValues; i++) {
-            View view = values.viewValues.keyAt(i);
-            if (isValidTarget(view)) {
-                addViewValues(included, view, values.viewValues.valueAt(i), false);
-            }
-        }
-        return included;
-    }
-
     /**
      * @hide
      */
@@ -470,6 +450,7 @@
             for (Transition childTransition : mTransitions) {
                 if (childTransition.isValidTarget(transitionValues.view)) {
                     childTransition.captureStartValues(transitionValues);
+                    transitionValues.targetedTransitions.add(childTransition);
                 }
             }
         }
@@ -481,6 +462,7 @@
             for (Transition childTransition : mTransitions) {
                 if (childTransition.isValidTarget(transitionValues.view)) {
                     childTransition.captureEndValues(transitionValues);
+                    transitionValues.targetedTransitions.add(childTransition);
                 }
             }
         }
diff --git a/core/java/android/transition/TransitionValues.java b/core/java/android/transition/TransitionValues.java
index 8989f89..11f2962 100644
--- a/core/java/android/transition/TransitionValues.java
+++ b/core/java/android/transition/TransitionValues.java
@@ -20,6 +20,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import java.util.ArrayList;
 import java.util.Map;
 
 /**
@@ -52,6 +53,11 @@
      */
     public final Map<String, Object> values = new ArrayMap<String, Object>();
 
+    /**
+     * The Transitions that targeted this view.
+     */
+    final ArrayList<Transition> targetedTransitions = new ArrayList<Transition>();
+
     @Override
     public boolean equals(Object other) {
         if (other instanceof TransitionValues) {
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index ba2d5b8..1ce19ce 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -33,6 +33,7 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -132,6 +133,8 @@
     private int mTitleTextColor;
     private int mSubtitleTextColor;
 
+    private boolean mEatingTouch;
+
     // Clear me after use.
     private final ArrayList<View> mTempViews = new ArrayList<View>();
 
@@ -1061,6 +1064,32 @@
         removeCallbacks(mShowOverflowMenuRunnable);
     }
 
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        // Toolbars always eat touch events, but should still respect the touch event dispatch
+        // contract. If the normal View implementation doesn't want the events, we'll just silently
+        // eat the rest of the gesture without reporting the events to the default implementation
+        // since that's what it expects.
+
+        final int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_DOWN) {
+            mEatingTouch = false;
+        }
+
+        if (!mEatingTouch) {
+            final boolean handled = super.onTouchEvent(ev);
+            if (action == MotionEvent.ACTION_DOWN && !handled) {
+                mEatingTouch = true;
+            }
+        }
+
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+            mEatingTouch = false;
+        }
+
+        return true;
+    }
+
     /**
      * @hide
      */
diff --git a/core/res/res/layout/action_mode_close_item_material.xml b/core/res/res/layout/action_mode_close_item_material.xml
index 8eb780b..89a1797 100644
--- a/core/res/res/layout/action_mode_close_item_material.xml
+++ b/core/res/res/layout/action_mode_close_item_material.xml
@@ -20,6 +20,7 @@
         android:clickable="true"
         android:paddingStart="8dip"
         android:src="?android:attr/actionModeCloseDrawable"
+        android:contentDescription="@string/action_mode_done"
         style="?android:attr/actionModeCloseButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 438d1fb..0e597d0 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5271,11 +5271,16 @@
         <attr name="viewportWidth" format="float"/>
         <!-- The height of the canvas the drawing is on. -->
         <attr name="viewportHeight" format="float"/>
+        <!-- The name of this vector drawable -->
+        <attr name="name" />
+        <!-- The opacity of the whole vector drawable, as a value between 0
+             (completely transparent) and 1 (completely opaque). -->
+        <attr name="alpha" />
     </declare-styleable>
 
     <!-- Defines the group used in VectorDrawables. -->
     <declare-styleable name="VectorDrawableGroup">
-        <!-- The Name of this group -->
+        <!-- The name of this group -->
         <attr name="name" />
         <!-- The amount to rotate the group -->
         <attr name="rotation" />
@@ -5295,7 +5300,7 @@
 
     <!-- Defines the path used in VectorDrawables. -->
     <declare-styleable name="VectorDrawablePath">
-        <!-- The Name of this path -->
+        <!-- The name of this path -->
         <attr name="name" />
         <!-- The width a path stroke -->
         <attr name="strokeWidth" format="float" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3907fc5..7599bf4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -339,6 +339,22 @@
          capability can provide power savings when wifi needs to be always kept on. -->
     <bool translatable="false" name="config_wifi_background_scan_support">false</bool>
 
+    <!-- Boolean indicating we re-try re-associating once upon disconnection and RSSI is high failure  -->
+    <bool translatable="true" name="config_wifi_enable_disconnection_debounce">true</bool>
+
+    <!-- Boolean indicating autojoin will prefer 5GHz and choose 5GHz BSSIDs -->
+    <bool translatable="true" name="config_wifi_enable_5GHz_preference">true</bool>
+
+    <!-- Integer specifying the basic autojoin parameters -->
+    <integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_threshold">-65</integer>
+    <integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_factor">5</integer>
+    <integer translatable="false" name="config_wifi_framework_current_association_hysteresis_high">16</integer>
+    <integer translatable="false" name="config_wifi_framework_current_association_hysteresis_low">10</integer>
+    <integer translatable="false" name="config_wifi_framework_5GHz_preference_penalty_threshold">-75</integer>
+    <integer translatable="false" name="config_wifi_framework_5GHz_preference_penalty_factor">2</integer>
+
+
+
     <!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
 
@@ -351,9 +367,24 @@
          point on the move. A value of 0 means no periodic scans will be used in the framework. -->
     <integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
 
-    <!-- Integer indicating associated scan interval in milliseconds -->
+    <!-- Integer indicating associated partial scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_framework_associated_scan_interval">10000</integer>
 
+    <!-- Integer indicating associated full scan backoff, representing a fraction: xx/8 -->
+    <integer translatable="false" name="config_wifi_framework_associated_full_scan_backoff">12</integer>
+
+    <!-- Integer indicating associated full scan max interval in milliseconds -->
+    <integer translatable="false" name="config_wifi_framework_associated_full_scan_max_interval">300000</integer>
+
+    <!-- Integer indicating associated full scan max total dwell time in milliseconds -->
+    <integer translatable="false" name="config_wifi_framework_associated_full_scan_max_total_dwell_time">500</integer>
+
+    <!-- Integer indicating associated full scan max num active channels -->
+    <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_active_channels">6</integer>
+
+    <!-- Integer indicating associated full scan max num passive channels -->
+    <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels">3</integer>
+
     <!-- Boolean indicating associated scan are allowed -->
     <bool translatable="false" name="config_wifi_framework_enable_associated_autojoin_scan">true</bool>
 
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 77b451f..7a2bbc1 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -412,7 +412,7 @@
      <dimen name="light_y">-200dp</dimen>
      <dimen name="light_z">800dp</dimen>
      <dimen name="light_radius">800dp</dimen>
-     <item type="dimen" format="float" name="ambient_shadow_alpha">0.06</item>
-     <item type="dimen" format="float" name="spot_shadow_alpha">0.16</item>
+     <item type="dimen" format="float" name="ambient_shadow_alpha">0.047</item>
+     <item type="dimen" format="float" name="spot_shadow_alpha">0.098</item>
 
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 117e235..d69a0f2 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -297,6 +297,21 @@
   <java-symbol type="bool" name="config_wifi_framework_enable_associated_autojoin_scan" />
   <java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
   <java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
+  <java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
+  <java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
+  <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
+  <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_current_association_hysteresis_high" />
+  <java-symbol type="integer" name="config_wifi_framework_current_association_hysteresis_low" />
+  <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_factor" />
+  <java-symbol type="integer" name="config_wifi_framework_associated_scan_interval" />
+  <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_backoff" />
+  <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_interval" />
+  <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_total_dwell_time" />
+  <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_active_channels" />
+  <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels" />
   <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
   <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
   <java-symbol type="integer" name="config_cursorWindowSize" />
@@ -315,7 +330,6 @@
   <java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
   <java-symbol type="integer" name="config_toastDefaultGravity" />
   <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
-  <java-symbol type="integer" name="config_wifi_framework_associated_scan_interval" />
   <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
   <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
   <java-symbol type="integer" name="db_connection_pool_size" />
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 2916d6c..cd6297b 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -825,7 +825,7 @@
 
     @Override
     public int getOpacity() {
-        return (mAlpha == 255 && mGradientState.mOpaqueOverBounds) ?
+        return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ?
                 PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
     }
 
@@ -1414,12 +1414,25 @@
         return mGradientState;
     }
 
+    private boolean isOpaqueForState() {
+        if (mGradientState.mStrokeWidth >= 0 && mStrokePaint != null
+                && !isOpaque(mStrokePaint.getColor())) {
+            return false;
+        }
+
+        if (!isOpaque(mFillPaint.getColor())) {
+            return false;
+        }
+
+        return true;
+    }
+
     @Override
     public void getOutline(Outline outline) {
         final GradientState st = mGradientState;
         final Rect bounds = getBounds();
         // only report non-zero alpha if shape being drawn is opaque
-        outline.setAlpha(st.mOpaqueOverShape ? (mAlpha / 255.0f) : 0.0f);
+        outline.setAlpha(st.mOpaqueOverShape && isOpaqueForState() ? (mAlpha / 255.0f) : 0.0f);
 
         switch (st.mShape) {
             case RECTANGLE:
@@ -1617,19 +1630,6 @@
             mOpaqueOverBounds = false;
             mOpaqueOverShape = false;
 
-            // First test opacity of all colors
-            if (mStrokeWidth > 0) {
-                if (mStrokeColorStateList != null) {
-                    if (!mStrokeColorStateList.isOpaque()) {
-                        return;
-                    }
-                }
-            }
-
-            if (mColorStateList != null && !mColorStateList.isOpaque()) {
-                return;
-            }
-
             if (mColors != null) {
                 for (int i = 0; i < mColors.length; i++) {
                     if (!isOpaque(mColors[i])) {
@@ -1651,10 +1651,6 @@
                     && mRadiusArray == null;
         }
 
-        private static boolean isOpaque(int color) {
-            return ((color >> 24) & 0xff) == 0xff;
-        }
-
         public void setStroke(
                 int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
             mStrokeWidth = width;
@@ -1690,6 +1686,10 @@
         }
     }
 
+    static boolean isOpaque(int color) {
+        return ((color >> 24) & 0xff) == 0xff;
+    }
+
     /**
      * Creates a new themed GradientDrawable based on the specified constant state.
      * <p>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 62eb4c8..bb6b1c9 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -42,7 +42,6 @@
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -195,6 +194,7 @@
     private VectorDrawableState mVectorState;
 
     private PorterDuffColorFilter mTintFilter;
+    private ColorFilter mColorFilter;
 
     private boolean mMutated;
 
@@ -216,7 +216,6 @@
         }
 
         mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
-        state.setColorFilter(mTintFilter);
     }
 
     @Override
@@ -255,22 +254,27 @@
             canvas.scale(-1.0f, 1.0f);
         }
 
-        if (!mAllowCaching) {
-            mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
-        } else {
-            Bitmap bitmap = mVectorState.mCachedBitmap;
-            if (bitmap == null || !mVectorState.canReuseCache(bounds.width(),
-                    bounds.height())) {
-                bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
-                        Bitmap.Config.ARGB_8888);
-                Canvas tmpCanvas = new Canvas(bitmap);
-                mVectorState.mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height());
-                mVectorState.mCachedBitmap = bitmap;
+        // Color filters always override tint filters.
+        final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
 
+        if (!mAllowCaching) {
+            // AnimatedVectorDrawable
+            if (!mVectorState.hasTranslucentRoot()) {
+                mVectorState.mVPathRenderer.draw(
+                        canvas, bounds.width(), bounds.height(), colorFilter);
+            } else {
+                mVectorState.createCachedBitmapIfNeeded(bounds);
+                mVectorState.updateCachedBitmap(bounds);
+                mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
+            }
+        } else {
+            // Static Vector Drawable case.
+            mVectorState.createCachedBitmapIfNeeded(bounds);
+            if (!mVectorState.canReuseCache()) {
+                mVectorState.updateCachedBitmap(bounds);
                 mVectorState.updateCacheStates();
             }
-            // The bitmap's size is the same as the bounds.
-            canvas.drawBitmap(bitmap, 0, 0, null);
+            mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
         }
 
         canvas.restoreToCount(saveCount);
@@ -291,18 +295,7 @@
 
     @Override
     public void setColorFilter(ColorFilter colorFilter) {
-        final VectorDrawableState state = mVectorState;
-        if (colorFilter != null) {
-            // Color filter overrides tint.
-            mTintFilter = null;
-        } else if (state.mTint != null && state.mTintMode != null) {
-            // Restore the tint filter, if we need one.
-            final int color = state.mTint.getColorForState(getState(), Color.TRANSPARENT);
-            mTintFilter = new PorterDuffColorFilter(color, state.mTintMode);
-            colorFilter = mTintFilter;
-        }
-
-        state.setColorFilter(colorFilter);
+        mColorFilter = colorFilter;
         invalidateSelf();
     }
 
@@ -312,7 +305,6 @@
         if (state.mTint != tint) {
             state.mTint = tint;
             mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
-            state.setColorFilter(mTintFilter);
             invalidateSelf();
         }
     }
@@ -323,7 +315,6 @@
         if (state.mTintMode != tintMode) {
             state.mTintMode = tintMode;
             mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
-            state.setColorFilter(mTintFilter);
             invalidateSelf();
         }
     }
@@ -339,7 +330,6 @@
         final VectorDrawableState state = mVectorState;
         if (state.mTint != null && state.mTintMode != null) {
             mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
-            state.setColorFilter(mTintFilter);
             invalidateSelf();
             return true;
         }
@@ -383,7 +373,6 @@
             }
 
             mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
-            state.setColorFilter(mTintFilter);
         }
 
         final VPathRenderer path = state.mVPathRenderer;
@@ -463,7 +452,6 @@
         inflateInternal(res, parser, attrs, theme);
 
         mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
-        state.setColorFilter(mTintFilter);
     }
 
     private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
@@ -514,6 +502,15 @@
             throw new XmlPullParserException(a.getPositionDescription() +
                     "<vector> tag requires height > 0");
         }
+
+        final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
+                pathRenderer.getAlpha());
+        pathRenderer.setAlpha(alphaInFloat);
+
+        pathRenderer.mRootName = a.getString(R.styleable.VectorDrawable_name);
+        if (pathRenderer.mRootName != null) {
+            pathRenderer.mVGTargetsMap.put(pathRenderer.mRootName, pathRenderer);
+        }
     }
 
     private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
@@ -647,6 +644,9 @@
         boolean mCachedAutoMirrored;
         boolean mCacheDirty;
 
+        /** Temporary paint object used to draw cached bitmaps. */
+        Paint mTempPaint;
+
         // Deep copy for mutate() or implicitly mutate.
         public VectorDrawableState(VectorDrawableState copy) {
             if (copy != null) {
@@ -659,24 +659,68 @@
                 if (copy.mVPathRenderer.mStrokePaint != null) {
                     mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
                 }
-                if (copy.mVPathRenderer.mColorFilter != null) {
-                    mVPathRenderer.mColorFilter = copy.mVPathRenderer.mColorFilter;
-                }
                 mTint = copy.mTint;
                 mTintMode = copy.mTintMode;
                 mAutoMirrored = copy.mAutoMirrored;
             }
         }
 
-        public boolean canReuseCache(int width, int height) {
+        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) {
+            // The bitmap's size is the same as the bounds.
+            final Paint p = getPaint(filter);
+            canvas.drawBitmap(mCachedBitmap, 0, 0, p);
+        }
+
+        public boolean hasTranslucentRoot() {
+            return mVPathRenderer.getRootAlpha() < 255;
+        }
+
+        /**
+         * @return null when there is no need for alpha paint.
+         */
+        public Paint getPaint(ColorFilter filter) {
+            if (!hasTranslucentRoot() && filter == null) {
+                return null;
+            }
+
+            if (mTempPaint == null) {
+                mTempPaint = new Paint();
+            }
+            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
+            mTempPaint.setColorFilter(filter);
+            return mTempPaint;
+        }
+
+        public void updateCachedBitmap(Rect bounds) {
+            mCachedBitmap.eraseColor(Color.TRANSPARENT);
+            Canvas tmpCanvas = new Canvas(mCachedBitmap);
+            mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null);
+        }
+
+        public void createCachedBitmapIfNeeded(Rect bounds) {
+            if (mCachedBitmap == null || !canReuseBitmap(bounds.width(),
+                    bounds.height())) {
+                mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
+                        Bitmap.Config.ARGB_8888);
+            }
+
+        }
+
+        public boolean canReuseBitmap(int width, int height) {
+            if (width == mCachedBitmap.getWidth()
+                    && height == mCachedBitmap.getHeight()) {
+                return true;
+            }
+            return false;
+        }
+
+        public boolean canReuseCache() {
             if (!mCacheDirty
                     && mCachedThemeAttrs == mThemeAttrs
                     && mCachedTint == mTint
                     && mCachedTintMode == mTintMode
                     && mCachedAutoMirrored == mAutoMirrored
-                    && width == mCachedBitmap.getWidth()
-                    && height == mCachedBitmap.getHeight()
-                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha())  {
+                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
                 return true;
             }
             return false;
@@ -699,12 +743,6 @@
                     || (mVPathRenderer != null && mVPathRenderer.canApplyTheme());
         }
 
-        public void setColorFilter(ColorFilter colorFilter) {
-            if (mVPathRenderer != null && mVPathRenderer.setColorFilter(colorFilter)) {
-                mCacheDirty = true;
-            }
-        }
-
         public VectorDrawableState() {
             mVPathRenderer = new VPathRenderer();
         }
@@ -752,7 +790,6 @@
 
         private Paint mStrokePaint;
         private Paint mFillPaint;
-        private ColorFilter mColorFilter;
         private PathMeasure mPathMeasure;
 
         /////////////////////////////////////////////////////
@@ -763,7 +800,8 @@
         float mBaseHeight = 0;
         float mViewportWidth = 0;
         float mViewportHeight = 0;
-        private int mRootAlpha = 0xFF;
+        int mRootAlpha = 0xFF;
+        String mRootName = null;
 
         final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
 
@@ -781,6 +819,17 @@
             return mRootAlpha;
         }
 
+        // setAlpha() and getAlpha() are used mostly for animation purpose, since
+        // Animator like to use alpha from 0 to 1.
+        public void setAlpha(float alpha) {
+            setRootAlpha((int) (alpha * 255));
+        }
+
+        @SuppressWarnings("unused")
+        public float getAlpha() {
+            return getRootAlpha() / 255.0f;
+        }
+
         public VPathRenderer(VPathRenderer copy) {
             mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
             mPath = new Path(copy.mPath);
@@ -791,6 +840,10 @@
             mViewportHeight = copy.mViewportHeight;
             mChangingConfigurations = copy.mChangingConfigurations;
             mRootAlpha = copy.mRootAlpha;
+            mRootName = copy.mRootName;
+            if (copy.mRootName != null) {
+                mVGTargetsMap.put(copy.mRootName, this);
+            }
         }
 
         public boolean canApplyTheme() {
@@ -847,25 +900,8 @@
             }
         }
 
-        public boolean setColorFilter(ColorFilter colorFilter) {
-            if (colorFilter != mColorFilter
-                    || (colorFilter != null && !colorFilter.equals(mColorFilter))) {
-                mColorFilter = colorFilter;
-
-                if (mFillPaint != null) {
-                    mFillPaint.setColorFilter(colorFilter);
-                }
-
-                if (mStrokePaint != null) {
-                    mStrokePaint.setColorFilter(colorFilter);
-                }
-                return true;
-            }
-            return false;
-        }
-
         private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
-                Canvas canvas, int w, int h) {
+                Canvas canvas, int w, int h, ColorFilter filter) {
             // Calculate current group's matrix by preConcat the parent's and
             // and the current one on the top of the stack.
             // Basically the Mfinal = Mviewport * M0 * M1 * M2;
@@ -880,21 +916,22 @@
                 if (child instanceof VGroup) {
                     VGroup childGroup = (VGroup) child;
                     drawGroupTree(childGroup, currentGroup.mStackedMatrix,
-                            canvas, w, h);
+                            canvas, w, h, filter);
                 } else if (child instanceof VPath) {
                     VPath childPath = (VPath) child;
-                    drawPath(currentGroup, childPath, canvas, w, h);
+                    drawPath(currentGroup, childPath, canvas, w, h, filter);
                 }
             }
         }
 
-        public void draw(Canvas canvas, int w, int h) {
+        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
             // Travese the tree in pre-order to draw.
-            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h);
+            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
         }
 
-        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h) {
-            final float scaleX =  w / mViewportWidth;
+        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
+                ColorFilter filter) {
+            final float scaleX = w / mViewportWidth;
             final float scaleY = h / mViewportHeight;
             final float minScale = Math.min(scaleX, scaleY);
 
@@ -937,19 +974,19 @@
                 if (fullPath.mFillColor != Color.TRANSPARENT) {
                     if (mFillPaint == null) {
                         mFillPaint = new Paint();
-                        mFillPaint.setColorFilter(mColorFilter);
                         mFillPaint.setStyle(Paint.Style.FILL);
                         mFillPaint.setAntiAlias(true);
                     }
-                    mFillPaint.setColor(applyAlpha(fullPath.mFillColor,
-                            fullPath.mFillAlpha));
-                    canvas.drawPath(mRenderPath, mFillPaint);
+
+                    final Paint fillPaint = mFillPaint;
+                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+                    fillPaint.setColorFilter(filter);
+                    canvas.drawPath(mRenderPath, fillPaint);
                 }
 
                 if (fullPath.mStrokeColor != Color.TRANSPARENT) {
                     if (mStrokePaint == null) {
                         mStrokePaint = new Paint();
-                        mStrokePaint.setColorFilter(mColorFilter);
                         mStrokePaint.setStyle(Paint.Style.STROKE);
                         mStrokePaint.setAntiAlias(true);
                     }
@@ -964,9 +1001,8 @@
                     }
 
                     strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
-
-                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor,
-                            fullPath.mStrokeAlpha));
+                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+                    strokePaint.setColorFilter(filter);
                     strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
                     canvas.drawPath(mRenderPath, strokePaint);
                 }
@@ -1256,7 +1292,7 @@
     /**
      * Clip path, which only has name and pathData.
      */
-    private static class VClipPath extends VPath{
+    private static class VClipPath extends VPath {
         public VClipPath() {
             // Empty constructor.
         }
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index c1ffa0a..35cc7a4 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -37,7 +37,7 @@
 
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
-    float heightFactor = 1.0f / 128;
+    float heightFactor = 1.0f / 86;
     const float geomFactor = 64;
 
     Caches& caches = Caches::getInstance();
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index e0901d0..f0a2072 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -34,6 +34,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Log;
 
 import com.android.internal.R;
@@ -110,6 +111,9 @@
     // Set to true if the phone is having emergency call.
     private volatile boolean mIsInEmergency;
 
+    // If Location function is enabled.
+    private volatile boolean mIsLocationEnabled = false;
+
     private final INetInitiatedListener mNetInitiatedListener;
 
     // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
@@ -132,7 +136,7 @@
     };
 
     public static class GpsNiResponse {
-        /* User reponse, one of the values in GpsUserResponseType */
+        /* User response, one of the values in GpsUserResponseType */
         int userResponse;
         /* Optional extra data to pass with the user response */
         Bundle extras;
@@ -154,8 +158,11 @@
                        Emergency call back mode will be checked by reading system properties
                        when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
                 */
-                mIsInEmergency |= PhoneNumberUtils.isEmergencyNumber(phoneNumber);
-                if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + mIsInEmergency);
+                setInEmergency(PhoneNumberUtils.isEmergencyNumber(phoneNumber));
+                if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + getInEmergency());
+            } else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
+                updateLocationMode();
+                if (DEBUG) Log.d(TAG, "location enabled :" + getLocationEnabled());
             }
         }
     };
@@ -179,8 +186,9 @@
             mNetInitiatedListener = netInitiatedListener;
         }
 
-        mIsSuplEsEnabled = isSuplEsEnabled;
+        setSuplEsEnabled(isSuplEsEnabled);
         mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
+        updateLocationMode();
         mTelephonyManager =
             (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
 
@@ -190,7 +198,7 @@
                 if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
                 // listening for emergency call ends
                 if (state == TelephonyManager.CALL_STATE_IDLE) {
-                    mIsInEmergency = false;
+                    setInEmergency(false);
                 }
             }
         };
@@ -198,27 +206,65 @@
 
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
+        intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
         mContext.registerReceiver(mBroadcastReciever, intentFilter);
     }
 
-    public void setSuplEsEnablement(boolean isEnabled)
-    {
+    public void setSuplEsEnabled(boolean isEnabled) {
         mIsSuplEsEnabled = isEnabled;
     }
 
+    public boolean getSuplEsEnabled() {
+        return mIsSuplEsEnabled;
+    }
+
+    /**
+     * Updates Location enabler based on location setting.
+     */
+    public void updateLocationMode() {
+        mIsLocationEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+    }
+
+    /**
+     * Checks if user agreed to use location.
+     */
+    public boolean getLocationEnabled() {
+        return mIsLocationEnabled;
+    }
+
+    // Note: Currently, there are two mechanisms involved to determine if a
+    // phone is in emergency mode:
+    // 1. If the user is making an emergency call, this is provided by activly
+    //    monitoring the outgoing phone number;
+    // 2. If the device is in a emergency callback state, this is provided by
+    //    system properties.
+    // If either one of above exists, the phone is considered in an emergency
+    // mode. Because of this complexity, we need to be careful about how to set
+    // and clear the emergency state.
+    public void setInEmergency(boolean isInEmergency) {
+        mIsInEmergency = isInEmergency;
+    }
+
+    public boolean getInEmergency() {
+        boolean isInEmergencyCallback = Boolean.parseBoolean(
+                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
+        return mIsInEmergency || isInEmergencyCallback;
+    }
+
+
     // Handles NI events from HAL
-    public void handleNiNotification(GpsNiNotification notif)
-    {
+    public void handleNiNotification(GpsNiNotification notif) {
         if (DEBUG) Log.d(TAG, "in handleNiNotification () :"
                         + " notificationId: " + notif.notificationId
                         + " requestorId: " + notif.requestorId
                         + " text: " + notif.text
-                        + " mIsSuplEsEnabled" + mIsSuplEsEnabled);
+                        + " mIsSuplEsEnabled" + getSuplEsEnabled()
+                        + " mIsLocationEnabled" + getLocationEnabled());
 
-        if (mIsSuplEsEnabled == false) {
-            handleNi(notif);
-        } else {
+        if (getSuplEsEnabled()) {
             handleNiInEs(notif);
+        } else {
+            handleNi(notif);
         }
 
         //////////////////////////////////////////////////////////////////////////
@@ -240,9 +286,18 @@
                         + " needNotify: " + notif.needNotify
                         + " needVerify: " + notif.needVerify
                         + " privacyOverride: " + notif.privacyOverride
-                        + " mPopupImmediately: " + mPopupImmediately);
+                        + " mPopupImmediately: " + mPopupImmediately
+                        + " mInEmergency: " + getInEmergency());
 
-        // legacy behaviour
+        if (getLocationEnabled() && !getInEmergency()) {
+            // Location is currently disabled, ignore all NI requests.
+            try {
+                mNetInitiatedListener.sendNiResponse(notif.notificationId,
+                                                     GPS_NI_RESPONSE_IGNORE);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in sendNiResponse");
+            }
+        }
         if (notif.needNotify) {
         // If NI does not need verify or the dialog is not requested
         // to pop up immediately, the dialog box will not pop up.
@@ -274,9 +329,6 @@
                     + " notificationId: " + notif.notificationId);
 
         // UE is in emergency mode when in emergency call mode or in emergency call back mode
-        boolean isUEInEmergencyMode = mIsInEmergency ||
-            Boolean.parseBoolean(SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
-
         /*
            1. When SUPL ES bit is off and UE is not in emergency mode:
                   Call handleNi() to do legacy behaviour.
@@ -288,7 +340,7 @@
                   Ignore the emergency SUPL INIT.
         */
         boolean isNiTypeES = (notif.niType == GPS_NI_TYPE_EMERGENCY_SUPL);
-        if (isNiTypeES != isUEInEmergencyMode) {
+        if (isNiTypeES != getInEmergency()) {
             try {
                 mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                      GPS_NI_RESPONSE_IGNORE);
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index d7ede34..56fa546 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -33,7 +33,35 @@
 
 /**
  * A class to encapsulate a collection of attributes describing information about an audio
- * player or recorder.
+ * stream.
+ * <p><code>AudioAttributes</code> supersede the notion of stream types (see for instance
+ * {@link AudioManager#STREAM_MUSIC} or {@link AudioManager#STREAM_ALARM}) for defining the
+ * behavior of audio playback. Attributes allow an application to specify more information than is
+ * conveyed in a stream type by allowing the application to define:
+ * <ul>
+ * <li>usage: "why" you are playing a sound, what is this sound used for. This is achieved with
+ *     the "usage" information. Examples of usage are {@link #USAGE_MEDIA} and {@link #USAGE_ALARM}.
+ *     These two examples are the closest to stream types, but more detailed use cases are
+ *     available. Usage information is more expressive than a stream type, and allows certain
+ *     platforms or routing policies to use this information for more refined volume or routing
+ *     decisions. Usage is the most important information to supply in <code>AudioAttributes</code>
+ *     and it is recommended to build any instance with this information supplied, see
+ *     {@link AudioAttributes.Builder} for exceptions.</li>
+ * <li>content type: "what" you are playing. The content type expresses the general category of
+ *     the content. This information is optional. But in case it is known (for instance
+ *     {@link #CONTENT_TYPE_MOVIE} for a movie streaming service or {@link #CONTENT_TYPE_MUSIC} for
+ *     a music playback application) this information might be used by the audio framework to
+ *     selectively configure some audio post-processing blocks.</li>
+ * <li>flags: "how" is playback to be affected, see the flag definitions for the specific playback
+ *     behaviors they control. </li>
+ * </ul>
+ * <p><code>AudioAttributes</code> are used for example in one of the {@link AudioTrack}
+ * constructors (see {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}),
+ * to configure a {@link MediaPlayer}
+ * (see {@link MediaPlayer#setAudioAttributes(AudioAttributes)} or a
+ * {@link android.app.Notification} (see {@link android.app.Notification#audioAttributes}). An
+ * <code>AudioAttributes</code> instance is built through its builder,
+ * {@link AudioAttributes.Builder}.
  */
 public final class AudioAttributes implements Parcelable {
     private final static String TAG = "AudioAttributes";
@@ -237,6 +265,22 @@
 
     /**
      * Builder class for {@link AudioAttributes} objects.
+     * <p> Here is an example where <code>Builder</code> is used to define the
+     * {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
+     *
+     * <pre class="prettyprint">
+     * AudioTrack myTrack = new AudioTrack(
+     *         new AudioAttributes.Builder()
+     *             .setUsage(AudioAttributes.USAGE_MEDIA)
+     *             .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
+     *             .build(),
+     *         myFormat, myBuffSize, AudioTrack.MODE_STREAM, mySession);
+     * </pre>
+     *
+     * <p>By default all types of information (usage, content type, flags) conveyed by an
+     * <code>AudioAttributes</code> instance are set to "unknown". Unknown information will be
+     * interpreted as a default value that is dependent on the context of use, for instance a
+     * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
      */
     public static class Builder {
         private int mUsage = USAGE_UNKNOWN;
@@ -247,6 +291,11 @@
 
         /**
          * Constructs a new Builder with the defaults.
+         * By default, usage and content type are respectively {@link AudioAttributes#USAGE_UNKNOWN}
+         * and {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}, and flags are 0. It is recommended to
+         * configure the usage (with {@link #setUsage(int)}) or deriving attributes from a legacy
+         * stream type (with {@link #setLegacyStreamType(int)}) before calling {@link #build()}
+         * to override any default playback behavior in terms of routing and volume management.
          */
         public Builder() {
         }
@@ -373,7 +422,9 @@
         }
 
         /**
-         * Adds attributes inferred from the legacy stream types.
+         * Sets attributes as inferred from the legacy stream types.
+         * Use this method when building an {@link AudioAttributes} instance to initialize some of
+         * the attributes by information derived from a legacy stream type.
          * @param streamType one of {@link AudioManager#STREAM_VOICE_CALL},
          *   {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
          *   {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
@@ -432,7 +483,6 @@
 
         /**
          * @hide
-         * CANDIDATE FOR PUBLIC API
          * Sets the capture preset.
          * Use this audio attributes configuration method when building an {@link AudioRecord}
          * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 704e4a1..54ebc6a 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -120,7 +120,9 @@
     // Attributes from XML meta data.
     private String mSetupActivity;
     private String mSettingsActivity;
+
     private int mType = TYPE_TUNER;
+    private HdmiDeviceInfo mHdmiDeviceInfo;
     private String mLabel;
     private Uri mIconUri;
     private boolean mIsConnectedToHdmiSwitch;
@@ -159,7 +161,7 @@
      * ResolveInfo, and HdmiDeviceInfo.
      *
      * @param service The ResolveInfo returned from the package manager about this TV input service.
-     * @param deviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
+     * @param hdmiDeviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
      * @param parentId The ID of this TV input's parent input. {@code null} if none exists.
      * @param iconUri The {@link android.net.Uri} to load the icon image. See
      *            {@link android.content.ContentResolver#openInputStream}. If it is {@code null},
@@ -170,12 +172,14 @@
      */
     @SystemApi
     public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
-            HdmiDeviceInfo deviceInfo, String parentId, String label, Uri iconUri)
+            HdmiDeviceInfo hdmiDeviceInfo, String parentId, String label, Uri iconUri)
                     throws XmlPullParserException, IOException {
-        boolean isConnectedToHdmiSwitch = (deviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
-        return createTvInputInfo(context, service, generateInputIdForHdmiDevice(
+        boolean isConnectedToHdmiSwitch = (hdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
+        TvInputInfo input = createTvInputInfo(context, service, generateInputIdForHdmiDevice(
                 new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
-                deviceInfo), parentId, TYPE_HDMI, label, iconUri, isConnectedToHdmiSwitch);
+                hdmiDeviceInfo), parentId, TYPE_HDMI, label, iconUri, isConnectedToHdmiSwitch);
+        input.mHdmiDeviceInfo = hdmiDeviceInfo;
+        return input;
     }
 
     /**
@@ -345,15 +349,27 @@
     }
 
     /**
-     * Returns the type of this TV input service.
+     * Returns the type of this TV input.
      */
     public int getType() {
         return mType;
     }
 
     /**
-     * Returns {@code true} if this TV input is pass-though which does not have any real channels
-     * in TvProvider. {@code false} otherwise.
+     * Returns the HDMI device information of this TV input.
+     * @hide
+     */
+    @SystemApi
+    public HdmiDeviceInfo getHdmiDeviceInfo() {
+        if (mType == TYPE_HDMI) {
+            return mHdmiDeviceInfo;
+        }
+        return null;
+    }
+
+    /**
+     * Returns {@code true} if this TV input is pass-though which does not have any real channels in
+     * TvProvider. {@code false} otherwise.
      *
      * @see TvContract#buildChannelUriForPassthroughInput(String)
      */
@@ -480,6 +496,7 @@
         dest.writeString(mSetupActivity);
         dest.writeString(mSettingsActivity);
         dest.writeInt(mType);
+        dest.writeParcelable(mHdmiDeviceInfo, flags);
         dest.writeParcelable(mIconUri, flags);
         dest.writeString(mLabel);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
@@ -552,6 +569,7 @@
         mSetupActivity = in.readString();
         mSettingsActivity = in.readString();
         mType = in.readInt();
+        mHdmiDeviceInfo = in.readParcelable(null);
         mIconUri = in.readParcelable(null);
         mLabel = in.readString();
         mIsConnectedToHdmiSwitch = in.readByte() == 1 ? true : false;
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_breadcrumb_arrow_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_breadcrumb_arrow_am_alpha.png
new file mode 100644
index 0000000..84573f6
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_breadcrumb_arrow_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_accept_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_accept_alpha.png
new file mode 100644
index 0000000..986d3fb
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_accept_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_cancel_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_cancel_alpha.png
new file mode 100644
index 0000000..ce443f9
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_cancel_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_select_item_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_select_item_alpha.png
new file mode 100644
index 0000000..a54e0ea
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_cab_select_item_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_dialog_alert_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_dialog_alert_alpha.png
new file mode 100644
index 0000000..6e65716
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_dialog_alert_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_dialog_info_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_dialog_info_alpha.png
new file mode 100644
index 0000000..35bd56e
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_dialog_info_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_album_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_album_alpha.png
new file mode 100644
index 0000000..64aa50b
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_album_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_apk_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_apk_alpha.png
new file mode 100644
index 0000000..7cbcb8b
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_apk_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_audio_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_audio_alpha.png
new file mode 100644
index 0000000..d6d79ec
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_audio_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_certificate_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_certificate_alpha.png
new file mode 100644
index 0000000..ca12928
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_certificate_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_codes_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_codes_alpha.png
new file mode 100644
index 0000000..c4afa37
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_codes_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_compressed_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_compressed_alpha.png
new file mode 100644
index 0000000..0b0aa04
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_compressed_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_contact_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_contact_am_alpha.png
new file mode 100644
index 0000000..ebd0535
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_contact_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_event_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_event_am_alpha.png
new file mode 100644
index 0000000..29cdbb7
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_event_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_excel_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_excel_alpha.png
new file mode 100644
index 0000000..ca349b6
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_excel_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_folder_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_folder_alpha.png
new file mode 100644
index 0000000..02249d2
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_folder_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_font_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_font_alpha.png
new file mode 100644
index 0000000..469b911
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_font_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_generic_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_generic_am_alpha.png
new file mode 100644
index 0000000..ef479c3
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_generic_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_image_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_image_alpha.png
new file mode 100644
index 0000000..3168d6f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_image_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_pdf_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_pdf_alpha.png
new file mode 100644
index 0000000..9bb4d66
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_pdf_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_powerpoint_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_powerpoint_alpha.png
new file mode 100644
index 0000000..88ba9ad
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_powerpoint_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_presentation_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_presentation_alpha.png
new file mode 100644
index 0000000..5fe18da
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_presentation_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_spreadsheet_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_spreadsheet_am_alpha.png
new file mode 100644
index 0000000..1d05f6f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_spreadsheet_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_text_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_text_am_alpha.png
new file mode 100644
index 0000000..c2308fe
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_text_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_video_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_video_am_alpha.png
new file mode 100644
index 0000000..9a173be
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_video_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_word_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_word_alpha.png
new file mode 100644
index 0000000..a564f5a
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_doc_word_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_folder_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_folder_alpha.png
new file mode 100644
index 0000000..c0c27a2
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_folder_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_grid_folder_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_grid_folder_alpha.png
new file mode 100644
index 0000000..ca6be0e
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_grid_folder_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png
new file mode 100644
index 0000000..13b20c6
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_hamburger_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_copy_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_copy_alpha.png
new file mode 100644
index 0000000..2dcf03e
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_copy_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png
new file mode 100644
index 0000000..07a78ed
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_delete_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_disconnect_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_disconnect_am_alpha.png
new file mode 100644
index 0000000..d7eb04f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_disconnect_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_new_folder_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_new_folder_am_alpha.png
new file mode 100644
index 0000000..879bf45
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_new_folder_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_overflow_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_overflow_alpha.png
new file mode 100644
index 0000000..2cd4137
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_overflow_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_rename_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_rename_am_alpha.png
new file mode 100644
index 0000000..268049e
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_rename_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_search_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_search_alpha.png
new file mode 100644
index 0000000..78fc61d
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_search_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_settings_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_settings_alpha.png
new file mode 100644
index 0000000..36e8e68
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_settings_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png
new file mode 100644
index 0000000..68831f3
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_share_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_sortby_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_sortby_am_alpha.png
new file mode 100644
index 0000000..827a92c
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_sortby_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_undo_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_undo_am_alpha.png
new file mode 100644
index 0000000..0f12b7d
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_undo_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_view_grid_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_view_grid_alpha.png
new file mode 100644
index 0000000..df1bac1
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_view_grid_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_view_list_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_view_list_alpha.png
new file mode 100644
index 0000000..9420374
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_menu_view_list_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_open_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_open_am_alpha.png
new file mode 100644
index 0000000..0394c5c
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_open_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_popout_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_popout_am_alpha.png
new file mode 100644
index 0000000..325d374
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_popout_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_download_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_download_alpha.png
new file mode 100644
index 0000000..87a5210
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_download_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_folder_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_folder_am_alpha.png
new file mode 100644
index 0000000..bb41a91
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_folder_am_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_recent_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_recent_alpha.png
new file mode 100644
index 0000000..baa723d
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_recent_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_sdcard_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_sdcard_alpha.png
new file mode 100644
index 0000000..39c737f
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_sdcard_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_usb_light_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_usb_light_alpha.png
new file mode 100644
index 0000000..88973e0
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_root_usb_light_alpha.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_subdirectory_arrow_am_alpha.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_subdirectory_arrow_am_alpha.png
new file mode 100644
index 0000000..8fddb85
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_subdirectory_arrow_am_alpha.png
Binary files differ
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index adff596..c7cf61a 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -55,7 +55,8 @@
 
         <service
             android:name=".renderer.PdfManipulationService"
-            android:isolatedProcess="true">
+            android:isolatedProcess="true"
+            android:process=":renderer">
         </service>
 
         <activity
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 239f006..429437d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -135,7 +135,7 @@
     private final DeathRecipient mDeathRecipient = new DeathRecipient() {
         @Override
         public void binderDied() {
-            mAdapterDeathObserver.onDied();
+            notifyPrintingAppDied();
         }
     };
 
@@ -180,7 +180,6 @@
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "Error calling start()", re);
             mState = STATE_FAILED;
-            mAdapterDeathObserver.onDied();
         }
     }
 
@@ -269,7 +268,6 @@
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "Error calling finish()", re);
             mState = STATE_FAILED;
-            mAdapterDeathObserver.onDied();
         }
     }
 
@@ -1108,6 +1106,15 @@
         }
     }
 
+    private void notifyPrintingAppDied() {
+        new Handler(mLooper).post(new Runnable() {
+            @Override
+            public void run() {
+                mAdapterDeathObserver.onDied();
+            }
+        });
+    }
+
     private static final class PrintDocumentAdapterObserver
             extends IPrintDocumentAdapterObserver.Stub {
         private final WeakReference<RemotePrintDocument> mWeakDocument;
@@ -1120,12 +1127,7 @@
         public void onDestroy() {
             final RemotePrintDocument document = mWeakDocument.get();
             if (document != null) {
-                new Handler(document.mLooper).post(new Runnable() {
-                    @Override
-                    public void run() {
-                        document.mAdapterDeathObserver.onDied();
-                    }
-                });
+                document.notifyPrintingAppDied();
             }
         }
     }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 625dc96..934ed38 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -193,11 +193,11 @@
     <!-- Default for Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, 1==on -->
     <integer name="def_heads_up_enabled">1</integer>
 
-    <!-- Default for Settings.Global.DEVICE_NAME $1=MODEL-->
-    <string name="def_device_name">%1$s</string>
-
     <!-- Default for Settings.Global.DEVICE_NAME $1=MANUFACTURER $2=MODEL-->
-    <string name="def_device_name_old">%1$s %2$s</string>
+    <string name="def_device_name">%1$s %2$s</string>
+
+    <!-- Default for Settings.Global.DEVICE_NAME $1=MODEL-->
+    <string name="def_device_name_simple">%1$s</string>
 
     <!-- Default for Settings.Secure.WAKE_GESTURE_ENABLED -->
     <bool name="def_wake_gesture_enabled">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index bdb167f..873257c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2609,11 +2609,11 @@
     }
 
     private String getOldDefaultDeviceName() {
-        return mContext.getResources().getString(R.string.def_device_name_old,
+        return mContext.getResources().getString(R.string.def_device_name,
                 Build.MANUFACTURER, Build.MODEL);
     }
 
     private String getDefaultDeviceName() {
-        return mContext.getResources().getString(R.string.def_device_name, Build.MODEL);
+        return mContext.getResources().getString(R.string.def_device_name_simple, Build.MODEL);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 18ef024..b71c9bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -257,7 +257,7 @@
                     (mMobileVisible ? "VISIBLE" : "GONE"),
                     mMobileStrengthId, mMobileTypeId));
 
-        mMobileType.setVisibility(!mWifiVisible || mRoaming ? View.VISIBLE : View.GONE);
+        mMobileType.setVisibility((mRoaming || mMobileTypeId != 0) ? View.VISIBLE : View.GONE);
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4d248c2..79d769a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -128,6 +128,8 @@
     private boolean mConnected = false;
     private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
     private String mConnectedNetworkTypeName;
+    private int mLastConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+
     private int mInetCondition = 0;
     private int mLastInetCondition = 0;
     private static final int INET_CONDITION_THRESHOLD = 50;
@@ -221,7 +223,7 @@
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
-        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
@@ -462,7 +464,7 @@
                         intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
                         intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
             refreshViews();
-        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
+        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
                  action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
             updateConnectivity(intent);
             refreshViews();
@@ -669,21 +671,28 @@
         }
     }
 
+    private int inetConditionForNetwork(int networkType) {
+        return (mInetCondition == 1 && mConnectedNetworkType == networkType) ? 1 : 0;
+    }
+
     private final void updateDataNetType() {
+        int inetCondition;
+        mDataTypeIconId = mQSDataTypeIconId = 0;
         if (mIsWimaxEnabled && mWimaxConnected) {
             // wimax is a special 4g network not handled by telephony
-            mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
+            inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
+            mDataIconList = TelephonyIcons.DATA_4G[inetCondition];
             mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_4g;
-            mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[mInetCondition];
+            mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition];
             mContentDescriptionDataType = mContext.getString(
                     R.string.accessibility_data_connection_4g);
         } else {
+            inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE);
+            final boolean showDataTypeIcon = (inetCondition > 0);
             switch (mDataNetType) {
                 case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                     if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
-                        mDataTypeIconId = 0;
-                        mQSDataTypeIconId = 0;
+                        mDataIconList = TelephonyIcons.DATA_G[inetCondition];
                         mContentDescriptionDataType = "";
                         break;
                     } else {
@@ -691,9 +700,10 @@
                     }
                 case TelephonyManager.NETWORK_TYPE_EDGE:
                     if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_e;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_E[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_E[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_e : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_E[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_edge);
                         break;
@@ -701,9 +711,10 @@
                         // fall through
                     }
                 case TelephonyManager.NETWORK_TYPE_UMTS:
-                    mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
-                    mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_3g;
-                    mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                    mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
+                    mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_3g : 0;
+                    mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
                     mContentDescriptionDataType = mContext.getString(
                             R.string.accessibility_data_connection_3g);
                     break;
@@ -712,15 +723,17 @@
                 case TelephonyManager.NETWORK_TYPE_HSPA:
                 case TelephonyManager.NETWORK_TYPE_HSPAP:
                     if (mHspaDataDistinguishable) {
-                        mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_h;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_H[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_H[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_h : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_H[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_3_5g);
                     } else {
-                        mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_3g;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_3g : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_3g);
                     }
@@ -728,9 +741,10 @@
                 case TelephonyManager.NETWORK_TYPE_CDMA:
                     if (!mShowAtLeastThreeGees) {
                         // display 1xRTT for IS95A/B
-                        mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_1x;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_1X[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_1x : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_cdma);
                         break;
@@ -739,9 +753,10 @@
                     }
                 case TelephonyManager.NETWORK_TYPE_1xRTT:
                     if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_1x;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_1X[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_1x : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_cdma);
                         break;
@@ -752,39 +767,43 @@
                 case TelephonyManager.NETWORK_TYPE_EVDO_A:
                 case TelephonyManager.NETWORK_TYPE_EVDO_B:
                 case TelephonyManager.NETWORK_TYPE_EHRPD:
-                    mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
-                    mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_3g;
-                    mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                    mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
+                    mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_3g : 0;
+                    mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
                     mContentDescriptionDataType = mContext.getString(
                             R.string.accessibility_data_connection_3g);
                     break;
                 case TelephonyManager.NETWORK_TYPE_LTE:
                     boolean show4GforLTE = mContext.getResources().getBoolean(R.bool.config_show4GForLTE);
                     if (show4GforLTE) {
-                        mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_4g;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_4G[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_4g : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_4g);
                     } else {
-                        mDataIconList = TelephonyIcons.DATA_LTE[mInetCondition];
-                        mDataTypeIconId = TelephonyIcons.ICON_LTE;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_LTE[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ? TelephonyIcons.ICON_LTE : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_lte);
                     }
                     break;
                 default:
                     if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_g;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_G[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_g : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_gprs);
                     } else {
-                        mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
-                        mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_3g;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                        mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
+                        mDataTypeIconId = showDataTypeIcon ?
+                                R.drawable.stat_sys_data_fully_connected_3g : 0;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
                         mContentDescriptionDataType = mContext.getString(
                                 R.string.accessibility_data_connection_3g);
                     }
@@ -967,9 +986,10 @@
     }
 
     private void updateWifiIcons() {
+        int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIFI);
         if (mWifiConnected) {
-            mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
-            mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
+            mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
+            mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
             mContentDescriptionWifi = mContext.getString(
                     AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
         } else {
@@ -1028,10 +1048,11 @@
     private void updateWimaxIcons() {
         if (mIsWimaxEnabled) {
             if (mWimaxConnected) {
+                int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
                 if (mWimaxIdle)
                     mWimaxIconId = WimaxIcons.WIMAX_IDLE;
                 else
-                    mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal];
+                    mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[inetCondition][mWimaxSignal];
                 mContentDescriptionWimax = mContext.getString(
                         AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]);
             } else {
@@ -1208,6 +1229,8 @@
             mContentDescriptionCombinedSignal = mHasMobileDataFeature
                 ? mContentDescriptionDataType : mContentDescriptionWifi;
 
+            int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE);
+
             mDataTypeIconId = 0;
             mQSDataTypeIconId = 0;
             if (isCdma()) {
@@ -1266,7 +1289,8 @@
          || mLastWimaxIconId                != mWimaxIconId
          || mLastDataTypeIconId             != mDataTypeIconId
          || mLastAirplaneMode               != mAirplaneMode
-         || mLastLocale                     != mLocale)
+         || mLastLocale                     != mLocale
+         || mLastConnectedNetworkType       != mConnectedNetworkType)
         {
             // NB: the mLast*s will be updated later
             for (SignalCluster cluster : mSignalClusters) {
@@ -1301,6 +1325,10 @@
             mLastInetCondition = mInetCondition;
         }
 
+        if (mLastConnectedNetworkType != mConnectedNetworkType) {
+            mLastConnectedNetworkType = mConnectedNetworkType;
+        }
+
         // the wimax icon on phones
         if (mLastWimaxIconId != mWimaxIconId) {
             mLastWimaxIconId = mWimaxIconId;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 083aa9b..f6e2e67 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1234,6 +1234,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
         // Register for events related to sdcard installation.
@@ -1688,11 +1689,12 @@
             String action = intent.getAction();
             boolean replacing = false;
             boolean added = false;
-            boolean rebind = false;
+            boolean changed = false;
             Bundle extras = intent.getExtras();
             String pkgList[] = null;
             if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
-                    Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                    Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
+                    Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                 Uri uri = intent.getData();
                 if (uri == null) {
                     return;
@@ -1701,7 +1703,43 @@
                 if (pkgName != null) {
                     pkgList = new String[] { pkgName };
                 }
-                rebind = added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+                changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
+
+                // At package-changed we only care about looking at new transport states
+                if (changed) {
+                    try {
+                        if (MORE_DEBUG) {
+                            Slog.i(TAG, "Package " + pkgName + " changed; rechecking");
+                        }
+                        // unbind existing possibly-stale connections to that package's transports
+                        synchronized (mTransports) {
+                            TransportConnection conn = mTransportConnections.get(pkgName);
+                            if (conn != null) {
+                                final ServiceInfo svc = conn.mTransport;
+                                ComponentName svcName =
+                                        new ComponentName(svc.packageName, svc.name);
+                                String flatName = svcName.flattenToShortString();
+                                Slog.i(TAG, "Unbinding " + svcName);
+
+                                mContext.unbindService(conn);
+                                mTransportConnections.remove(pkgName);
+                                mTransports.remove(mTransportNames.get(flatName));
+                                mTransportNames.remove(flatName);
+                            }
+                        }
+                        // and then (re)bind as appropriate
+                        PackageInfo app = mPackageManager.getPackageInfo(pkgName, 0);
+                        checkForTransportAndBind(app);
+                    } catch (NameNotFoundException e) {
+                        // Nope, can't find it - just ignore
+                        if (MORE_DEBUG) {
+                            Slog.w(TAG, "Can't find changed package " + pkgName);
+                        }
+                    }
+                    return; // nothing more to do in the PACKAGE_CHANGED case
+                }
+
+                added = Intent.ACTION_PACKAGE_ADDED.equals(action);
                 replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
                 added = true;
@@ -1737,17 +1775,15 @@
 
                         // Transport maintenance: rebind to known existing transports that have
                         // just been updated; and bind to any newly-installed transport services.
-                        if (rebind) {
-                            synchronized (mTransportConnections) {
-                                final TransportConnection conn = mTransportConnections.get(packageName);
-                                if (conn != null) {
-                                    if (DEBUG) {
-                                        Slog.i(TAG, "Transport package changed; rebinding");
-                                    }
-                                    bindTransport(conn.mTransport);
-                                } else {
-                                    checkForTransportAndBind(app);
+                        synchronized (mTransports) {
+                            final TransportConnection conn = mTransportConnections.get(packageName);
+                            if (conn != null) {
+                                if (MORE_DEBUG) {
+                                    Slog.i(TAG, "Transport package changed; rebinding");
                                 }
+                                bindTransport(conn.mTransport);
+                            } else {
+                                checkForTransportAndBind(app);
                             }
                         }
 
@@ -1840,7 +1876,7 @@
         intent.setComponent(svcName);
 
         TransportConnection connection;
-        synchronized (mTransportConnections) {
+        synchronized (mTransports) {
             connection = mTransportConnections.get(transport.packageName);
             if (null == connection) {
                 connection = new TransportConnection(transport);
@@ -8462,31 +8498,24 @@
         return list;
     }
 
-    // Select which transport to use for the next backup operation.  If the given
-    // name is not one of the available transports, no action is taken and the method
-    // returns null.
+    // Select which transport to use for the next backup operation.
     public String selectBackupTransport(String transport) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                 "selectBackupTransport");
 
         synchronized (mTransports) {
-            String prevTransport = null;
-            if (mTransports.get(transport) != null) {
-                final long oldId = Binder.clearCallingIdentity();
-                try {
-                    prevTransport = mCurrentTransport;
-                    mCurrentTransport = transport;
-                    Settings.Secure.putString(mContext.getContentResolver(),
-                            Settings.Secure.BACKUP_TRANSPORT, transport);
-                } finally {
-                    Binder.restoreCallingIdentity(oldId);
-                }
+            final long oldId = Binder.clearCallingIdentity();
+            try {
+                String prevTransport = mCurrentTransport;
+                mCurrentTransport = transport;
+                Settings.Secure.putString(mContext.getContentResolver(),
+                        Settings.Secure.BACKUP_TRANSPORT, transport);
                 Slog.v(TAG, "selectBackupTransport() set " + mCurrentTransport
                         + " returning " + prevTransport);
-            } else {
-                Slog.w(TAG, "Attempt to select unavailable transport " + transport);
+                return prevTransport;
+            } finally {
+                Binder.restoreCallingIdentity(oldId);
             }
-            return prevTransport;
         }
     }
 
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index ef6e07c..c3465d1 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -631,7 +631,7 @@
     @Override
     public int checkPackage(int uid, String packageName) {
         synchronized (this) {
-            if (getOpsLocked(uid, packageName, true) != null) {
+            if (getOpsRawLocked(uid, packageName, true) != null) {
                 return AppOpsManager.MODE_ALLOWED;
             } else {
                 return AppOpsManager.MODE_ERRORED;
@@ -769,6 +769,15 @@
     }
 
     private Ops getOpsLocked(int uid, String packageName, boolean edit) {
+        if (uid == 0) {
+            packageName = "root";
+        } else if (uid == Process.SHELL_UID) {
+            packageName = "com.android.shell";
+        }
+        return getOpsRawLocked(uid, packageName, edit);
+    }
+
+    private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
         HashMap<String, Ops> pkgOps = mUidOps.get(uid);
         if (pkgOps == null) {
             if (!edit) {
@@ -777,11 +786,6 @@
             pkgOps = new HashMap<String, Ops>();
             mUidOps.put(uid, pkgOps);
         }
-        if (uid == 0) {
-            packageName = "root";
-        } else if (uid == Process.SHELL_UID) {
-            packageName = "com.android.shell";
-        }
         Ops ops = pkgOps.get(packageName);
         if (ops == null) {
             if (!edit) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 75090db..55d8c09 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -251,7 +251,7 @@
 
     private Context mContext;
     private int mNetworkPreference;
-    private int mActiveDefaultNetwork = -1;
+    private int mActiveDefaultNetwork = TYPE_NONE;
     // 0 is full bad, 100 is full good
     private int mDefaultInetConditionPublished = 0;
 
@@ -886,15 +886,6 @@
         return getNetworkInfo(mActiveDefaultNetwork, uid);
     }
 
-    // only called when the default request is satisfied
-    private void updateActiveDefaultNetwork(NetworkAgentInfo nai) {
-        if (nai != null) {
-            mActiveDefaultNetwork = nai.networkInfo.getType();
-        } else {
-            mActiveDefaultNetwork = TYPE_NONE;
-        }
-    }
-
     /**
      * Find the first Provisioning network.
      *
@@ -1794,6 +1785,7 @@
     }
 
     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, String msg) {
+        if (nai.network == null) return false;
         final NetworkAgentInfo officialNai;
         synchronized (mNetworkForNetId) {
             officialNai = mNetworkForNetId.get(nai.network.netId);
@@ -1933,10 +1925,16 @@
                     }
                     break;
                 }
-                case NetworkMonitor.EVENT_NETWORK_VALIDATED: {
+                case NetworkMonitor.EVENT_NETWORK_TESTED: {
                     NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
                     if (isLiveNetworkAgent(nai, "EVENT_NETWORK_VALIDATED")) {
-                        handleConnectionValidated(nai);
+                        boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
+                        if (valid) {
+                            if (DBG) log("Validated " + nai.name());
+                            nai.validated = true;
+                            rematchNetworkAndRequests(nai);
+                        }
+                        updateInetCondition(nai, valid);
                     }
                     break;
                 }
@@ -2057,7 +2055,7 @@
                     if (nri.isRequest == false) continue;
                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
-                            (nai != null ? nai.currentScore : 0), 0, nri.request);
+                            (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
                 }
             } else {
                 loge("Error connecting NetworkFactory");
@@ -2136,7 +2134,7 @@
                                 request.networkCapabilities.satisfiedByNetworkCapabilities(
                                 existing.networkCapabilities) &&
                                 (alternative == null ||
-                                 alternative.currentScore < existing.currentScore)) {
+                                 alternative.getCurrentScore() < existing.getCurrentScore())) {
                             alternative = existing;
                         }
                     }
@@ -2169,8 +2167,9 @@
         for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
             if (DBG) log("handleRegisterNetworkRequest checking " + network.name());
             if (newCap.satisfiedByNetworkCapabilities(network.networkCapabilities)) {
-                if (DBG) log("apparently satisfied.  currentScore=" + network.currentScore);
-                if ((bestNetwork == null) || bestNetwork.currentScore < network.currentScore) {
+                if (DBG) log("apparently satisfied.  currentScore=" + network.getCurrentScore());
+                if ((bestNetwork == null) ||
+                        bestNetwork.getCurrentScore() < network.getCurrentScore()) {
                     if (!nri.isRequest) {
                         // Not setting bestNetwork here as a listening NetworkRequest may be
                         // satisfied by multiple Networks.  Instead the request is added to
@@ -2194,7 +2193,7 @@
             bestNetwork.addRequest(nri.request);
             mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
             notifyNetworkCallback(bestNetwork, nri);
-            score = bestNetwork.currentScore;
+            score = bestNetwork.getCurrentScore();
             if (nri.request.legacyType != TYPE_NONE) {
                 mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
             }
@@ -4516,19 +4515,34 @@
         updateTcpBufferSizes(newNetwork);
     }
 
-    private void handleConnectionValidated(NetworkAgentInfo newNetwork) {
-        if (newNetwork == null) {
-            loge("Unknown NetworkAgentInfo in handleConnectionValidated");
-            return;
-        }
-        if (newNetwork.validated) return;
-        newNetwork.validated = true;
+    // Handles a network appearing or improving its score.
+    //
+    // - Evaluates all current NetworkRequests that can be
+    //   satisfied by newNetwork, and reassigns to newNetwork
+    //   any such requests for which newNetwork is the best.
+    //
+    // - Tears down any Networks that as a result are no longer
+    //   needed. A network is needed if it is the best network for
+    //   one or more NetworkRequests, or if it is a VPN.
+    //
+    // - Tears down newNetwork if it is validated but turns out to be
+    //   unneeded. Does not tear down newNetwork if it is
+    //   unvalidated, because future validation may improve
+    //   newNetwork's score enough that it is needed.
+    //
+    // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
+    // it does not remove NetworkRequests that other Networks could better satisfy.
+    // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
+    // This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
+    // as it performs better by a factor of the number of Networks.
+    private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork) {
         boolean keep = newNetwork.isVPN();
         boolean isNewDefault = false;
-        if (DBG) log("handleConnectionValidated for "+newNetwork.name());
-        // check if any NetworkRequest wants this NetworkAgent
+        if (DBG) log("rematching " + newNetwork.name());
+        // Find and migrate to this Network any NetworkRequests for
+        // which this network is now the best.
         ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
-        if (VDBG) log(" new Network has: " + newNetwork.networkCapabilities);
+        if (VDBG) log(" network has: " + newNetwork.networkCapabilities);
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
             NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
             if (newNetwork == currentNetwork) {
@@ -4543,18 +4557,21 @@
             if (nri.request.networkCapabilities.satisfiedByNetworkCapabilities(
                     newNetwork.networkCapabilities)) {
                 if (!nri.isRequest) {
+                    // This is not a request, it's a callback listener.
+                    // Add it to newNetwork regardless of score.
                     newNetwork.addRequest(nri.request);
                     continue;
                 }
+
                 // next check if it's better than any current network we're using for
                 // this request
                 if (VDBG) {
                     log("currentScore = " +
-                            (currentNetwork != null ? currentNetwork.currentScore : 0) +
-                            ", newScore = " + newNetwork.currentScore);
+                            (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
+                            ", newScore = " + newNetwork.getCurrentScore());
                 }
                 if (currentNetwork == null ||
-                        currentNetwork.currentScore < newNetwork.currentScore) {
+                        currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) {
                     if (currentNetwork != null) {
                         if (DBG) log("   accepting network in place of " + currentNetwork.name());
                         currentNetwork.networkRequests.remove(nri.request.requestId);
@@ -4569,13 +4586,16 @@
                         mLegacyTypeTracker.add(nri.request.legacyType, newNetwork);
                     }
                     keep = true;
+                    // Tell NetworkFactories about the new score, so they can stop
+                    // trying to connect if they know they cannot match it.
                     // TODO - this could get expensive if we have alot of requests for this
                     // network.  Think about if there is a way to reduce this.  Push
                     // netid->request mapping to each factory?
-                    sendUpdatedScoreToFactories(nri.request, newNetwork.currentScore);
+                    sendUpdatedScoreToFactories(nri.request, newNetwork.getCurrentScore());
                     if (mDefaultRequest.requestId == nri.request.requestId) {
                         isNewDefault = true;
-                        updateActiveDefaultNetwork(newNetwork);
+                        // TODO: Remove following line.  It's redundant with makeDefault call.
+                        mActiveDefaultNetwork = newNetwork.networkInfo.getType();
                         if (newNetwork.linkProperties != null) {
                             updateTcpBufferSizes(newNetwork);
                             setDefaultDnsSystemProperties(
@@ -4591,12 +4611,13 @@
                             mLegacyTypeTracker.remove(currentNetwork.networkInfo.getType(),
                                                       currentNetwork);
                         }
-                        mDefaultInetConditionPublished = 100;
+                        mDefaultInetConditionPublished = newNetwork.validated ? 100 : 0;
                         mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
                     }
                 }
             }
         }
+        // Linger any networks that are no longer needed.
         for (NetworkAgentInfo nai : affectedNetworks) {
             boolean teardown = !nai.isVPN();
             for (int i = 0; i < nai.networkRequests.size() && teardown; i++) {
@@ -4624,6 +4645,7 @@
         }
         if (keep) {
             if (isNewDefault) {
+                // Notify system services that this network is up.
                 makeDefault(newNetwork);
                 synchronized (ConnectivityService.this) {
                     // have a new default network, release the transition wakelock in
@@ -4640,6 +4662,7 @@
 
             // Notify battery stats service about this network, both the normal
             // interface and any stacked links.
+            // TODO: Avoid redoing this; this must only be done once when a network comes online.
             try {
                 final IBatteryStats bs = BatteryStatsService.getService();
                 final int type = newNetwork.networkInfo.getType();
@@ -4655,7 +4678,12 @@
             }
 
             notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE);
-        } else {
+        } else if (newNetwork.validated) {
+            // Only tear down validated networks here.  Leave unvalidated to either become
+            // validated (and get evaluated against peers, one losing here) or
+            // NetworkMonitor reports a bad network and we tear it down then.
+            // TODO: Could teardown unvalidated networks when their NetworkCapabilities
+            // satisfy no NetworkRequests.
             if (DBG && newNetwork.networkRequests.size() != 0) {
                 loge("tearing down network with live requests:");
                 for (int i=0; i < newNetwork.networkRequests.size(); i++) {
@@ -4667,6 +4695,46 @@
         }
     }
 
+    // Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
+    // being disconnected.
+    // If only one Network's score or capabilities have been modified since the last time
+    // this function was called, pass this Network in via the "changed" arugment, otherwise
+    // pass null.
+    // If only one Network has been changed but its NetworkCapabilities have not changed,
+    // pass in the Network's score (from getCurrentScore()) prior to the change via
+    // "oldScore", otherwise pass changed.getCurrentScore() or 0 if "changed" is null.
+    private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
+        // TODO: This may get slow.  The "changed" parameter is provided for future optimization
+        // to avoid the slowness.  It is not simply enough to process just "changed", for
+        // example in the case where "changed"'s score decreases and another network should begin
+        // satifying a NetworkRequest that "changed" currently satisfies.
+
+        // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
+        // can only add more NetworkRequests satisfied by "changed", and this is exactly what
+        // rematchNetworkAndRequests() handles.
+        if (changed != null && oldScore < changed.getCurrentScore()) {
+            rematchNetworkAndRequests(changed);
+        } else {
+            for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+                rematchNetworkAndRequests(nai);
+            }
+        }
+    }
+
+    private void updateInetCondition(NetworkAgentInfo nai, boolean valid) {
+        // Don't bother updating until we've graduated to validated at least once.
+        if (!nai.validated) return;
+        // For now only update icons for default connection.
+        // TODO: Update WiFi and cellular icons separately. b/17237507
+        if (!isDefaultNetwork(nai)) return;
+
+        int newInetCondition = valid ? 100 : 0;
+        // Don't repeat publish.
+        if (newInetCondition == mDefaultInetConditionPublished) return;
+
+        mDefaultInetConditionPublished = newInetCondition;
+        sendInetConditionBroadcast(nai.networkInfo);
+    }
 
     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
         NetworkInfo.State state = newInfo.getState();
@@ -4721,12 +4789,14 @@
                 }
                 // TODO: support proxy per network.
             }
-            // Make default network if we have no default.  Any network is better than no network.
+            // Consider network even though it is not yet validated.
+            // TODO: All the if-statement conditions can be removed now that validation only confers
+            // a score increase.
             if (mNetworkForRequestId.get(mDefaultRequest.requestId) == null &&
                     networkAgent.isVPN() == false &&
                     mDefaultRequest.networkCapabilities.satisfiedByNetworkCapabilities(
                     networkAgent.networkCapabilities)) {
-                makeDefault(networkAgent);
+                rematchNetworkAndRequests(networkAgent);
             }
         } else if (state == NetworkInfo.State.DISCONNECTED ||
                 state == NetworkInfo.State.SUSPENDED) {
@@ -4752,23 +4822,11 @@
             score = 0;
         }
 
-        nai.currentScore = score;
+        final int oldScore = nai.getCurrentScore();
+        nai.setCurrentScore(score);
 
-        // TODO - This will not do the right thing if this network is lowering
-        // its score and has requests that can be served by other
-        // currently-active networks, or if the network is increasing its
-        // score and other networks have requests that can be better served
-        // by this network.
-        //
-        // Really we want to see if any of our requests migrate to other
-        // active/lingered networks and if any other requests migrate to us (depending
-        // on increasing/decreasing currentScore.  That's a bit of work and probably our
-        // score checking/network allocation code needs to be modularized so we can understand
-        // (see handleConnectionValided for an example).
-        //
-        // As a first order approx, lets just advertise the new score to factories.  If
-        // somebody can beat it they will nominate a network and our normal net replacement
-        // code will fire.
+        if (nai.created) rematchAllNetworksAndRequests(nai, oldScore);
+
         for (int i = 0; i < nai.networkRequests.size(); i++) {
             NetworkRequest nr = nai.networkRequests.valueAt(i);
             // Don't send listening requests to factories. b/17393458
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 2896f60..6f378fd 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -26,7 +27,9 @@
 import android.os.UserHandle;
 import android.service.persistentdata.IPersistentDataBlockService;
 import android.util.Slog;
+
 import com.android.internal.R;
+
 import libcore.io.IoUtils;
 
 import java.io.DataInputStream;
@@ -241,6 +244,10 @@
 
         @Override
         public void setOemUnlockEnabled(boolean enabled) {
+            // do not allow monkey to flip the flag
+            if (ActivityManager.isUserAMonkey()) {
+                return;
+            }
             enforceOemUnlockPermission();
             FileOutputStream outputStream;
             try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2885b83..2c39691 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -413,7 +413,7 @@
      * List of intents that were used to start the most recent tasks.
      */
     ArrayList<TaskRecord> mRecentTasks;
-    ArraySet<TaskRecord> mTmpRecents = new ArraySet<TaskRecord>();
+    ArrayList<TaskRecord> mTmpRecents = new ArrayList<TaskRecord>();
 
     /**
      * For addAppTask: cached of the last activity component that was added.
@@ -3857,6 +3857,86 @@
         mTaskPersister.wakeup(null, true);
     }
 
+    // Sort by taskId
+    private Comparator<TaskRecord> mTaskRecordComparator = new Comparator<TaskRecord>() {
+        @Override
+        public int compare(TaskRecord lhs, TaskRecord rhs) {
+            return rhs.taskId - lhs.taskId;
+        }
+    };
+
+    // Extract the affiliates of the chain containing mRecentTasks[start].
+    private int processNextAffiliateChain(int start) {
+        final TaskRecord startTask = mRecentTasks.get(start);
+        final int affiliateId = startTask.mAffiliatedTaskId;
+
+        // Quick identification of isolated tasks. I.e. those not launched behind.
+        if (startTask.taskId == affiliateId && startTask.mPrevAffiliate == null &&
+                startTask.mNextAffiliate == null) {
+            // There is still a slim chance that there are other tasks that point to this task
+            // and that the chain is so messed up that this task no longer points to them but
+            // the gain of this optimization outweighs the risk.
+            startTask.inRecents = true;
+            return start + 1;
+        }
+
+        // Remove all tasks that are affiliated to affiliateId and put them in mTmpRecents.
+        mTmpRecents.clear();
+        for (int i = mRecentTasks.size() - 1; i >= start; --i) {
+            final TaskRecord task = mRecentTasks.get(i);
+            if (task.mAffiliatedTaskId == affiliateId) {
+                mRecentTasks.remove(i);
+                mTmpRecents.add(task);
+            }
+        }
+
+        // Sort them all by taskId. That is the order they were create in and that order will
+        // always be correct.
+        Collections.sort(mTmpRecents, mTaskRecordComparator);
+
+        // Go through and fix up the linked list.
+        // The first one is the end of the chain and has no next.
+        final TaskRecord first = mTmpRecents.get(0);
+        first.inRecents = true;
+        if (first.mNextAffiliate != null) {
+            Slog.w(TAG, "Link error 1 first.next=" + first.mNextAffiliate);
+            first.setNextAffiliate(null);
+            mTaskPersister.wakeup(first, false);
+        }
+        // Everything in the middle is doubly linked from next to prev.
+        final int tmpSize = mTmpRecents.size();
+        for (int i = 0; i < tmpSize - 1; ++i) {
+            final TaskRecord next = mTmpRecents.get(i);
+            final TaskRecord prev = mTmpRecents.get(i + 1);
+            if (next.mPrevAffiliate != prev) {
+                Slog.w(TAG, "Link error 2 next=" + next + " prev=" + next.mPrevAffiliate +
+                        " setting prev=" + prev);
+                next.setPrevAffiliate(prev);
+                mTaskPersister.wakeup(next, false);
+            }
+            if (prev.mNextAffiliate != next) {
+                Slog.w(TAG, "Link error 3 prev=" + prev + " next=" + prev.mNextAffiliate +
+                        " setting next=" + next);
+                prev.setNextAffiliate(next);
+                mTaskPersister.wakeup(prev, false);
+            }
+            prev.inRecents = true;
+        }
+        // The last one is the beginning of the list and has no prev.
+        final TaskRecord last = mTmpRecents.get(tmpSize - 1);
+        if (last.mPrevAffiliate != null) {
+            Slog.w(TAG, "Link error 4 last.prev=" + last.mPrevAffiliate);
+            last.setPrevAffiliate(null);
+            mTaskPersister.wakeup(last, false);
+        }
+
+        // Insert the group back into mRecentTasks at start.
+        mRecentTasks.addAll(start, mTmpRecents);
+
+        // Let the caller know where we left off.
+        return start + tmpSize;
+    }
+
     /**
      * Update the recent tasks lists: make sure tasks should still be here (their
      * applications / activities still exist), update their availability, fixup ordering
@@ -3969,51 +4049,9 @@
         }
 
         // Verify the affiliate chain for each task.
-        for (int i = 0; i < N; ) {
-            TaskRecord task = mRecentTasks.remove(i);
-            if (mTmpRecents.contains(task)) {
-                continue;
-            }
-            int affiliatedTaskId = task.mAffiliatedTaskId;
-            while (true) {
-                TaskRecord next = task.mNextAffiliate;
-                if (next == null) {
-                    break;
-                }
-                if (next.mAffiliatedTaskId != affiliatedTaskId) {
-                    Slog.e(TAG, "Error in Recents: next.affiliatedTaskId=" +
-                            next.mAffiliatedTaskId + " affiliatedTaskId=" + affiliatedTaskId);
-                    task.setNextAffiliate(null);
-                    if (next.mPrevAffiliate == task) {
-                        next.setPrevAffiliate(null);
-                    }
-                    break;
-                }
-                if (next.mPrevAffiliate != task) {
-                    Slog.e(TAG, "Error in Recents chain prev.mNextAffiliate=" +
-                            next.mPrevAffiliate + " task=" + task);
-                    next.setPrevAffiliate(null);
-                    task.setNextAffiliate(null);
-                    break;
-                }
-                if (!mRecentTasks.contains(next)) {
-                    Slog.e(TAG, "Error in Recents: next=" + next + " not in mRecentTasks");
-                    task.setNextAffiliate(null);
-                    // We know that next.mPrevAffiliate is always task, from above, so clear
-                    // its previous affiliate.
-                    next.setPrevAffiliate(null);
-                    break;
-                }
-                task = next;
-            }
-            // task is now the end of the list
-            do {
-                mRecentTasks.remove(task);
-                mRecentTasks.add(i++, task);
-                mTmpRecents.add(task);
-                task.inRecents = true;
-            } while ((task = task.mPrevAffiliate) != null);
+        for (int i = 0; i < N; i = processNextAffiliateChain(i)) {
         }
+
         mTmpRecents.clear();
         // mRecentTasks is now in sorted, affiliated order.
     }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index bba786d..957d705 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -43,12 +43,16 @@
     public Network network;
     public LinkProperties linkProperties;
     public NetworkCapabilities networkCapabilities;
-    public int currentScore;
     public final NetworkMonitor networkMonitor;
     public final NetworkMisc networkMisc;
     public boolean created;
     public boolean validated;
 
+    // This represents the last score received from the NetworkAgent.
+    private int currentScore;
+    // Penalty applied to scores of Networks that have not been validated.
+    private static final int UNVALIDATED_SCORE_PENALTY = 40;
+
     // The list of NetworkRequests being satisfied by this Network.
     public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
     public final ArrayList<NetworkRequest> networkLingered = new ArrayList<NetworkRequest>();
@@ -80,11 +84,33 @@
         return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
     }
 
+    // Get the current score for this Network.  This may be modified from what the
+    // NetworkAgent sent, as it has modifiers applied to it.
+    public int getCurrentScore() {
+        // TODO: We may want to refactor this into a NetworkScore class that takes a base score from
+        // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
+        // score.  The NetworkScore class would provide a nice place to centralize score constants
+        // so they are not scattered about the transports.
+
+        int score = currentScore;
+
+        if (!validated) score -= UNVALIDATED_SCORE_PENALTY;
+
+        if (score < 0) score = 0;
+
+        return score;
+    }
+
+    public void setCurrentScore(int newScore) {
+        currentScore = newScore;
+    }
+
     public String toString() {
         return "NetworkAgentInfo{ ni{" + networkInfo + "}  network{" +
                 network + "}  lp{" +
                 linkProperties + "}  nc{" +
-                networkCapabilities + "}  Score{" + currentScore + "} }";
+                networkCapabilities + "}  Score{" + getCurrentScore() + "} " +
+                "validated{" + validated + "} created{" + created + "} }";
     }
 
     public String name() {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 96872a7..9e33205 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -95,6 +95,18 @@
             "android.net.netmon.captive_portal_logged_in";
     private static final String LOGGED_IN_RESULT = "result";
 
+    // After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
+    // The network should be used as a default internet connection.  It was found to be:
+    // 1. a functioning network providing internet access, or
+    // 2. a captive portal and the user decided to use it as is.
+    public static final int NETWORK_TEST_RESULT_VALID = 0;
+    // After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
+    // The network should not be used as a default internet connection.  It was found to be:
+    // 1. a captive portal and the user is prompted to sign-in, or
+    // 2. a captive portal and the user did not want to use it, or
+    // 3. a broken network (e.g. DNS failed, connect failed, HTTP request failed).
+    public static final int NETWORK_TEST_RESULT_INVALID = 1;
+
     private static final int BASE = Protocol.BASE_NETWORK_MONITOR;
 
     /**
@@ -104,10 +116,11 @@
     public static final int CMD_NETWORK_CONNECTED = BASE + 1;
 
     /**
-     * Inform ConnectivityService that the network is validated.
+     * Inform ConnectivityService that the network has been tested.
      * obj = NetworkAgentInfo
+     * arg1 = One of the NETWORK_TESTED_RESULT_* constants.
      */
-    public static final int EVENT_NETWORK_VALIDATED = BASE + 2;
+    public static final int EVENT_NETWORK_TESTED = BASE + 2;
 
     /**
      * Inform NetworkMonitor to linger a network.  The Monitor should
@@ -216,6 +229,9 @@
     private String mServer;
     private boolean mIsCaptivePortalCheckEnabled = false;
 
+    // Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
+    private boolean mUserDoesNotWant = false;
+
     public boolean systemReady = false;
 
     private State mDefaultState = new DefaultState();
@@ -290,9 +306,23 @@
 
     private class OfflineState extends State {
         @Override
+        public void enter() {
+            mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
+                    NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
+        }
+
+        @Override
         public boolean processMessage(Message message) {
             if (DBG) log(getName() + message.toString());
-            return NOT_HANDLED;
+                        switch (message.what) {
+                case CMD_FORCE_REEVALUATION:
+                    // If the user has indicated they explicitly do not want to use this network,
+                    // don't allow a reevaluation as this will be pointless and could result in
+                    // the user being annoyed with repeated unwanted notifications.
+                    return mUserDoesNotWant ? HANDLED : NOT_HANDLED;
+                default:
+                    return NOT_HANDLED;
+            }
         }
     }
 
@@ -300,8 +330,8 @@
         @Override
         public void enter() {
             if (DBG) log("Validated");
-            mConnectivityServiceHandler.sendMessage(
-                    obtainMessage(EVENT_NETWORK_VALIDATED, mNetworkAgentInfo));
+            mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
+                    NETWORK_TEST_RESULT_VALID, 0, mNetworkAgentInfo));
         }
 
         @Override
@@ -393,6 +423,8 @@
 
         @Override
         public void enter() {
+            mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
+                    NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
             // Wait for user to select sign-in notifcation.
             mUserRespondedBroadcastReceiver = new UserRespondedBroadcastReceiver(
                     ++mUserPromptedToken);
@@ -477,6 +509,7 @@
                     if (message.arg1 != mCaptivePortalLoggedInToken)
                         return HANDLED;
                     if (message.arg2 == 0) {
+                        mUserDoesNotWant = true;
                         // TODO: Should teardown network.
                         transitionTo(mOfflineState);
                     } else {
@@ -544,6 +577,12 @@
                     mConnectivityServiceHandler.sendMessage(
                             obtainMessage(EVENT_NETWORK_LINGER_COMPLETE, mNetworkAgentInfo));
                     return HANDLED;
+                case CMD_FORCE_REEVALUATION:
+                    // Ignore reevaluation attempts when lingering.  A reevaluation could result
+                    // in a transition to the validated state which would abort the linger
+                    // timeout.  Lingering is the result of score assessment; validity is
+                    // irrelevant.
+                    return HANDLED;
                 default:
                     return NOT_HANDLED;
             }
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index d0447bc..9df21a2 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -170,6 +170,7 @@
                 mRunningJob = null;
                 mParams = null;
                 mExecutionStartTimeElapsed = 0L;
+                removeOpTimeOut();
                 return false;
             }
             try {
@@ -299,7 +300,7 @@
         public void handleMessage(Message message) {
             switch (message.what) {
                 case MSG_SERVICE_BOUND:
-                    removeMessages(MSG_TIMEOUT);
+                    removeOpTimeOut();
                     handleServiceBoundH();
                     break;
                 case MSG_CALLBACK:
@@ -307,7 +308,7 @@
                         Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob + " v:" +
                                 (mVerb >= 0 ? VERB_STRINGS[mVerb] : "[invalid]"));
                     }
-                    removeMessages(MSG_TIMEOUT);
+                    removeOpTimeOut();
 
                     if (mVerb == VERB_STARTING) {
                         final boolean workOngoing = message.arg2 == 1;
@@ -498,7 +499,7 @@
          * VERB_STOPPING.
          */
         private void sendStopMessageH() {
-            mCallbackHandler.removeMessages(MSG_TIMEOUT);
+            removeOpTimeOut();
             if (mVerb != VERB_EXECUTING) {
                 Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob);
                 closeAndCleanupJobH(false /* reschedule */);
@@ -540,7 +541,7 @@
                 service = null;
                 mAvailable = true;
             }
-            removeMessages(MSG_TIMEOUT);
+            removeOpTimeOut();
             removeMessages(MSG_CALLBACK);
             removeMessages(MSG_SERVICE_BOUND);
             removeMessages(MSG_CANCEL);
@@ -555,7 +556,7 @@
      * on with life.
      */
     private void scheduleOpTimeOut() {
-        mCallbackHandler.removeMessages(MSG_TIMEOUT);
+        removeOpTimeOut();
 
         final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
                 EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
@@ -568,4 +569,9 @@
         mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
         mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
     }
+
+
+    private void removeOpTimeOut() {
+        mCallbackHandler.removeMessages(MSG_TIMEOUT);
+    }
 }
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 11818d8..df846a8 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -494,7 +494,7 @@
                     Log.d(TAG, "SIM STATE is ready, SIM MCC/MNC is " + mccMnc);
                     synchronized (mLock) {
                         reloadGpsProperties(context, mProperties);
-                        mNIHandler.setSuplEsEnablement(mSuplEsEnabled);
+                        mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
                     }
                 }
             }
@@ -590,6 +590,7 @@
                 com.android.internal.R.array.config_gpsParameters);
         for (String item : configValues) {
             Log.d(TAG, "GpsParamsResource: " + item);
+            // We need to support "KEY =", but not "=VALUE".
             String[] split = item.split("=");
             if (split.length == 2) {
                 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index efaf253..95332bc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3716,7 +3716,7 @@
         synchronized (this) {
             // Only SYSTEM_UID can override the userSetupComplete
             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
-                    && isUserSetupComplete(userHandle)) {
+                    && hasUserSetupCompleted(userHandle)) {
                 throw new IllegalStateException(
                         "Trying to set profile owner but user is already set-up.");
             }
@@ -3773,10 +3773,14 @@
 
     @Override
     public boolean hasUserSetupCompleted() {
+        return hasUserSetupCompleted(UserHandle.getCallingUserId());
+    }
+
+    private boolean hasUserSetupCompleted(int userHandle) {
         if (!mHasFeature) {
             return true;
         }
-        DevicePolicyData policy = getUserData(UserHandle.getCallingUserId());
+        DevicePolicyData policy = getUserData(userHandle);
         // If policy is null, return true, else check if the setup has completed.
         return policy == null || policy.mUserSetupComplete;
     }
@@ -3888,16 +3892,10 @@
         if (callingId == Process.SHELL_UID || callingId == Process.ROOT_UID) {
             return AccountManager.get(mContext).getAccounts().length == 0;
         } else {
-            return Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.DEVICE_PROVISIONED, 0) == 0;
+            return !hasUserSetupCompleted(UserHandle.USER_OWNER);
         }
     }
 
-    private boolean isUserSetupComplete(int userId) {
-        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.USER_SETUP_COMPLETE, 0, userId) > 0;
-    }
-
     private void enforceCrossUserPermission(int userHandle) {
         if (userHandle < 0) {
             throw new IllegalArgumentException("Invalid userId " + userHandle);
diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml b/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml
new file mode 100644
index 0000000..1a81866
--- /dev/null
+++ b/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
+        android:duration="9000"
+        android:propertyName="alpha"
+        android:valueFrom="1.0"
+        android:valueTo="0.0"/>
+
+</set>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml
index 19b82ad..8b0ceda 100644
--- a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml
@@ -37,5 +37,8 @@
     <target
         android:name="rotationGroup"
         android:animation="@anim/trim_path_animation04" />
+    <target
+        android:name="rootGroup"
+        android:animation="@anim/trim_path_animation06" />
 
 </animated-vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
index 2c8b751..69ae62c 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
@@ -14,10 +14,12 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:name="rootGroup"
         android:height="64dp"
         android:width="64dp"
         android:viewportHeight="600"
-        android:viewportWidth="600" >
+        android:viewportWidth="600"
+        android:alpha="0.5" >
 
     <group
         android:name="rotationGroup"
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
index f165cde..05bf166 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
@@ -31,6 +31,8 @@
             R.drawable.animation_vector_progress_bar,
             R.drawable.animation_vector_drawable_favorite,
             R.drawable.animation_vector_drawable01,
+            // Duplicate to test constant state.
+            R.drawable.animation_vector_drawable01,
     };
 
     @Override
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index aeaff71..9ece434 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -186,6 +186,8 @@
     public static final int DISABLED_AUTH_FAILURE                           = 3;
     /** @hide */
     public static final int DISABLED_ASSOCIATION_REJECT                     = 4;
+    /** @hide */
+    public static final int DISABLED_BY_WIFI_MANAGER                        = 5;
 
     /**
      * The ID number that the supplicant uses to identify this
@@ -438,11 +440,7 @@
 
     /** @hide
      * 5GHz band is prefered low over 2.4 if the 5GHz RSSI is higher than this threshold */
-    public static int A_BAND_PREFERENCE_RSSI_THRESHOLD_LOW = -65;
-
-    /** @hide
-     * 5GHz band is prefered hard over 2.4 if the 5GHz RSSI is higher than this threshold */
-    public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -55;
+    public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65;
 
     /** @hide
      * 5GHz band is penalized if the 5GHz RSSI is lower than this threshold **/
@@ -457,6 +455,12 @@
      ***/
     public static int HOME_NETWORK_RSSI_BOOST = 5;
 
+    /** @hide
+     * RSSI boost for configuration which use autoJoinUseAggressiveJoinAttemptThreshold
+     * To be more aggressive when initially attempting to auto join
+     */
+    public static int MAX_INITIAL_AUTO_JOIN_RSSI_BOOST = 8;
+
     /**
      * @hide
      * A summary of the RSSI and Band status for that configuration
@@ -594,6 +598,11 @@
     /** @hide */
     public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE  = 128;
     /** @hide */
+    public static final int AUTO_JOIN_DISABLED_NO_CREDENTIALS = 160;
+    /** @hide */
+    public static final int AUTO_JOIN_DISABLED_USER_ACTION = 161;
+
+    /** @hide */
     public static final int AUTO_JOIN_DELETED  = 200;
 
     /**
@@ -664,6 +673,18 @@
 
     /**
      * @hide
+     * Indicate that we didn't auto-join because rssi was too low
+     */
+    public boolean autoJoinBailedDueToLowRssi;
+
+    /**
+     * @hide
+     * AutoJoin even though RSSI is 10dB below threshold
+     */
+    public int autoJoinUseAggressiveJoinAttemptThreshold;
+
+    /**
+     * @hide
      * Number of time the scorer overrode a the priority based choice, when comparing two
      * WifiConfigurations, note that since comparing WifiConfiguration happens very often
      * potentially at every scan, this number might become very large, even on an idle
@@ -881,11 +902,10 @@
         if (this.autoJoinStatus > 0) {
             sbuf.append(" autoJoinStatus ").append(this.numConnectionFailures).append("\n");
         }
-        if (this.didSelfAdd || this.selfAdded) {
-            if (this.didSelfAdd) sbuf.append(" didSelfAdd");
-            if (this.selfAdded) sbuf.append(" selfAdded");
-            if (this.noInternetAccess) sbuf.append(" noInternetAccess");
-
+        if (this.didSelfAdd) sbuf.append(" didSelfAdd");
+        if (this.selfAdded) sbuf.append(" selfAdded");
+        if (this.noInternetAccess) sbuf.append(" noInternetAccess");
+        if (this.didSelfAdd || this.selfAdded || this.noInternetAccess) {
             sbuf.append("\n");
         }
         sbuf.append(" KeyMgmt:");
@@ -950,21 +970,41 @@
         if (this.preSharedKey != null) {
             sbuf.append('*');
         }
-
+        sbuf.append("\nEnterprise config:\n");
         sbuf.append(enterpriseConfig);
-        sbuf.append('\n');
 
+        sbuf.append("IP config:\n");
         sbuf.append(mIpConfiguration.toString());
 
-        if (this.creatorUid != 0)  sbuf.append("uid=" + Integer.toString(creatorUid));
-        if (this.autoJoinBSSID != null) sbuf.append("autoJoinBSSID=" + autoJoinBSSID);
+        if (this.creatorUid != 0)  sbuf.append(" uid=" + Integer.toString(creatorUid));
+        if (this.autoJoinBSSID != null) sbuf.append(" autoJoinBSSID=" + autoJoinBSSID);
+        long now_ms = System.currentTimeMillis();
         if (this.blackListTimestamp != 0) {
-            long now_ms = System.currentTimeMillis();
+            sbuf.append('\n');
             long diff = now_ms - this.blackListTimestamp;
             if (diff <= 0) {
-                sbuf.append("blackListed since <incorrect>");
+                sbuf.append(" blackListed since <incorrect>");
             } else {
-                sbuf.append("blackListed since ").append(Long.toString(diff/1000)).append( "sec");
+                sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec");
+            }
+        }
+        if (this.lastConnected != 0) {
+            sbuf.append('\n');
+            long diff = now_ms - this.lastConnected;
+            if (diff <= 0) {
+                sbuf.append("lastConnected since <incorrect>");
+            } else {
+                sbuf.append("lastConnected: ").append(Long.toString(diff/1000)).append( "sec");
+            }
+        }
+        if (this.lastConnectionFailure != 0) {
+            sbuf.append('\n');
+            long diff = now_ms - this.lastConnectionFailure;
+            if (diff <= 0) {
+                sbuf.append("lastConnectionFailure since <incorrect>");
+            } else {
+                sbuf.append("lastConnectionFailure: ").append(Long.toString(diff/1000));
+                sbuf.append( "sec");
             }
         }
         sbuf.append('\n');
@@ -984,15 +1024,29 @@
                 }
             }
         }
-        sbuf.append(" triggeredLow: ").append(numUserTriggeredWifiDisableLowRSSI);
-        sbuf.append(" triggeredBad: ").append(numUserTriggeredWifiDisableBadRSSI);
-        sbuf.append(" triggeredNotHigh: ").append(numUserTriggeredWifiDisableNotHighRSSI);
+        if (this.scanResultCache != null) {
+            sbuf.append("scan cache:  ");
+            for(ScanResult result : this.scanResultCache.values()) {
+                sbuf.append("{").append(result.BSSID).append(",").append(result.frequency);
+                sbuf.append(",").append(result.level).append(",st=");
+                sbuf.append(result.autoJoinStatus).append("} ");
+            }
+            sbuf.append('\n');
+        }
+        sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI);
+        sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI);
+        sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI);
         sbuf.append('\n');
-        sbuf.append(" ticksLow: ").append(numTicksAtLowRSSI);
-        sbuf.append(" ticksBad: ").append(numTicksAtBadRSSI);
-        sbuf.append(" ticksNotHigh: ").append(numTicksAtNotHighRSSI);
+        sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI);
+        sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI);
+        sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI);
         sbuf.append('\n');
-        sbuf.append(" triggeredJoin: ").append(numUserTriggeredJoinAttempts);
+        sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts);
+        sbuf.append('\n');
+        sbuf.append("autoJoinBailedDueToLowRssi: ").append(this.autoJoinBailedDueToLowRssi);
+        sbuf.append('\n');
+        sbuf.append("autoJoinUseAggressiveJoinAttemptThreshold: ");
+        sbuf.append(this.autoJoinUseAggressiveJoinAttemptThreshold);
         sbuf.append('\n');
 
         return sbuf.toString();
@@ -1310,6 +1364,9 @@
             numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
             numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
             autoJoinBSSID = source.autoJoinBSSID;
+            autoJoinUseAggressiveJoinAttemptThreshold
+                    = source.autoJoinUseAggressiveJoinAttemptThreshold;
+            autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi;
         }
     }
 
@@ -1370,7 +1427,8 @@
         dest.writeInt(numTicksAtBadRSSI);
         dest.writeInt(numTicksAtNotHighRSSI);
         dest.writeInt(numUserTriggeredJoinAttempts);
-
+        dest.writeInt(autoJoinUseAggressiveJoinAttemptThreshold);
+        dest.writeInt(autoJoinBailedDueToLowRssi ? 1 : 0);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -1427,6 +1485,8 @@
                 config.numTicksAtBadRSSI = in.readInt();
                 config.numTicksAtNotHighRSSI = in.readInt();
                 config.numUserTriggeredJoinAttempts = in.readInt();
+                config.autoJoinUseAggressiveJoinAttemptThreshold = in.readInt();
+                config.autoJoinBailedDueToLowRssi = in.readInt() != 0;
                 return config;
             }