Merge "Report button opacity for current state, fix button shadows" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index a66204e..e9da398 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4328,9 +4328,9 @@
     method public void setAllowEnterTransitionOverlap(boolean);
     method public void setAllowReturnTransitionOverlap(boolean);
     method public void setArguments(android.os.Bundle);
-    method public void setEnterSharedElementTransitionCallback(android.app.SharedElementCallback);
+    method public void setEnterSharedElementCallback(android.app.SharedElementCallback);
     method public void setEnterTransition(android.transition.Transition);
-    method public void setExitSharedElementTransitionCallback(android.app.SharedElementCallback);
+    method public void setExitSharedElementCallback(android.app.SharedElementCallback);
     method public void setExitTransition(android.transition.Transition);
     method public void setHasOptionsMenu(boolean);
     method public void setInitialSavedState(android.app.Fragment.SavedState);
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/app/Fragment.java b/core/java/android/app/Fragment.java
index 4374622..a95abab 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1628,7 +1628,7 @@
      * @param callback Used to manipulate the shared element transitions on this Fragment
      *                 when added not as a pop from the back stack.
      */
-    public void setEnterSharedElementTransitionCallback(SharedElementCallback callback) {
+    public void setEnterSharedElementCallback(SharedElementCallback callback) {
         if (callback == null) {
             callback = SharedElementCallback.NULL_CALLBACK;
         }
@@ -1636,13 +1636,20 @@
     }
 
     /**
+     * @hide
+     */
+    public void setEnterSharedElementTransitionCallback(SharedElementCallback callback) {
+        setEnterSharedElementCallback(callback);
+    }
+
+    /**
      * When custom transitions are used with Fragments, the exit transition callback
      * is called when this Fragment is attached or detached when popping the back stack.
      *
      * @param callback Used to manipulate the shared element transitions on this Fragment
      *                 when added as a pop from the back stack.
      */
-    public void setExitSharedElementTransitionCallback(SharedElementCallback callback) {
+    public void setExitSharedElementCallback(SharedElementCallback callback) {
         if (callback == null) {
             callback = SharedElementCallback.NULL_CALLBACK;
         }
@@ -1650,6 +1657,13 @@
     }
 
     /**
+     * @hide
+     */
+    public void setExitSharedElementTransitionCallback(SharedElementCallback callback) {
+        setExitSharedElementCallback(callback);
+    }
+
+    /**
      * Sets the Transition that will be used to move Views into the initial scene. The entering
      * Views will be those that are regular Views or ViewGroups that have
      * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java
index 82d8e5b..d772743 100644
--- a/core/java/android/app/SharedElementCallback.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -32,8 +32,8 @@
  * Listener provided in
  * {@link Activity#setEnterSharedElementCallback(SharedElementCallback)} and
  * {@link Activity#setExitSharedElementCallback(SharedElementCallback)} as well as
- * {@link Fragment#setEnterSharedElementTransitionCallback(SharedElementCallback)} and
- * {@link Fragment#setExitSharedElementTransitionCallback(SharedElementCallback)}
+ * {@link Fragment#setEnterSharedElementCallback(SharedElementCallback)} and
+ * {@link Fragment#setExitSharedElementCallback(SharedElementCallback)}
  * to monitor the Shared element transitions. The events can be used to customize Activity
  * and Fragment Transition behavior.
  */
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/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/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/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 62eb4c8..dd87699 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -256,21 +256,22 @@
         }
 
         if (!mAllowCaching) {
-            mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
+            // AnimatedVectorDrawable
+            if (!mVectorState.hasTranslucentRoot()) {
+                mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
+            } else {
+                mVectorState.createCachedBitmapIfNeeded(bounds);
+                mVectorState.updateCachedBitmap(bounds);
+                mVectorState.drawCachedBitmapWithRootAlpha(canvas);
+            }
         } 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;
-
+            // 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);
         }
 
         canvas.restoreToCount(saveCount);
@@ -514,6 +515,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,
@@ -668,15 +678,60 @@
             }
         }
 
-        public boolean canReuseCache(int width, int height) {
+        // TODO: Support colorFilter here.
+        public void drawCachedBitmapWithRootAlpha(Canvas canvas) {
+            Paint alphaPaint = getRootAlphaPaint();
+            // The bitmap's size is the same as the bounds.
+            canvas.drawBitmap(mCachedBitmap, 0, 0, alphaPaint);
+        }
+
+        public boolean hasTranslucentRoot() {
+            return mVPathRenderer.getRootAlpha() < 255;
+        }
+
+        /**
+         * @return null when there is no need for alpha paint.
+         */
+        public Paint getRootAlphaPaint() {
+            Paint paint = null;
+            boolean needsAlphaPaint = hasTranslucentRoot();
+            if (needsAlphaPaint) {
+                paint = new Paint();
+                paint.setAlpha(mVPathRenderer.getRootAlpha());
+            }
+            return paint;
+        }
+
+        public void updateCachedBitmap(Rect bounds) {
+            mCachedBitmap.eraseColor(Color.TRANSPARENT);
+            Canvas tmpCanvas = new Canvas(mCachedBitmap);
+            mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height());
+        }
+
+        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;
@@ -763,7 +818,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 +837,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 +858,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() {
@@ -894,7 +965,7 @@
         }
 
         private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h) {
-            final float scaleX =  w / mViewportWidth;
+            final float scaleX = w / mViewportWidth;
             final float scaleY = h / mViewportHeight;
             final float minScale = Math.min(scaleX, scaleY);
 
@@ -1256,7 +1327,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/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/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