Merge "Explicitly set Settings background to white" into lmp-dev
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a19fbd3..702ac6b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -7498,23 +7498,32 @@
 
         final String action = getAction();
         if (ACTION_CHOOSER.equals(action)) {
+            // Inspect contained intents to see if we need to migrate extras. We
+            // don't promote ClipData to the parent, since ChooserActivity will
+            // already start the picked item as the caller, and we can't combine
+            // the flags in a safe way.
+
+            boolean migrated = false;
             try {
-                // Inspect target intent to see if we need to migrate
-                final Intent target = getParcelableExtra(EXTRA_INTENT);
-                if (target != null && target.migrateExtraStreamToClipData()) {
-                    // Since we migrated in child, we need to promote ClipData
-                    // and flags to ourselves to grant.
-                    setClipData(target.getClipData());
-                    addFlags(target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION
-                            | FLAG_GRANT_WRITE_URI_PERMISSION
-                            | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
-                            | FLAG_GRANT_PREFIX_URI_PERMISSION));
-                    return true;
-                } else {
-                    return false;
+                final Intent intent = getParcelableExtra(EXTRA_INTENT);
+                if (intent != null) {
+                    migrated |= intent.migrateExtraStreamToClipData();
                 }
             } catch (ClassCastException e) {
             }
+            try {
+                final Parcelable[] intents = getParcelableArrayExtra(EXTRA_INITIAL_INTENTS);
+                if (intents != null) {
+                    for (int i = 0; i < intents.length; i++) {
+                        final Intent intent = (Intent) intents[i];
+                        if (intent != null) {
+                            migrated |= intent.migrateExtraStreamToClipData();
+                        }
+                    }
+                }
+            } catch (ClassCastException e) {
+            }
+            return migrated;
 
         } else if (ACTION_SEND.equals(action)) {
             try {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 907d2ae..618195a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -34,7 +34,6 @@
 import android.hardware.camera2.utils.ArrayUtils;
 import android.hardware.camera2.utils.ListUtils;
 import android.hardware.camera2.utils.ParamsUtils;
-import android.hardware.camera2.utils.SizeAreaComparator;
 import android.util.Log;
 import android.util.Range;
 import android.util.Size;
@@ -88,6 +87,9 @@
 
     static final int UNKNOWN_MODE = -1;
 
+    // Maximum difference between a preview size aspect ratio and a jpeg size aspect ratio
+    private static final float PREVIEW_ASPECT_RATIO_TOLERANCE = 0.01f;
+
     /*
      * Development hijinks: Lie about not supporting certain capabilities
      *
@@ -103,6 +105,7 @@
     static final boolean LIE_ABOUT_AWB_STATE = false;
     static final boolean LIE_ABOUT_AWB = false;
 
+
     /**
      * Create characteristics for a legacy device by mapping the {@code parameters}
      * and {@code info}
@@ -262,6 +265,64 @@
          * remapping to public format constants.
          */
         List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
+        List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
+        /*
+         * Work-around for b/17589233:
+         * - Some HALs's largest preview size aspect ratio does not match the largest JPEG size AR
+         * - This causes a large amount of problems with focus/metering because it's relative to
+         *   preview, making the difference between the JPEG and preview viewport inaccessible
+         * - This boils down to metering or focusing areas being "arbitrarily" cropped
+         *   in the capture result.
+         * - Work-around the HAL limitations by removing all of the largest preview sizes
+         *   until we get one with the same aspect ratio as the jpeg size.
+         */
+        {
+            SizeAreaComparator areaComparator = new SizeAreaComparator();
+
+            // Sort preview to min->max
+            Collections.sort(previewSizes, areaComparator);
+
+            Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes);
+            float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height;
+
+            if (VERBOSE) {
+                Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f",
+                        maxJpegSize.width, maxJpegSize.height, jpegAspectRatio));
+            }
+
+            // Now remove preview sizes from the end (largest->smallest) until aspect ratio matches
+            while (!previewSizes.isEmpty()) {
+                int index = previewSizes.size() - 1; // max is always at the end
+                Camera.Size size = previewSizes.get(index);
+
+                float previewAspectRatio = size.width * 1.0f / size.height;
+
+                if (Math.abs(jpegAspectRatio - previewAspectRatio) >=
+                        PREVIEW_ASPECT_RATIO_TOLERANCE) {
+                    previewSizes.remove(index); // Assume removing from end is O(1)
+
+                    if (VERBOSE) {
+                        Log.v(TAG, String.format(
+                                "mapScalerStreamConfigs - removed preview size %dx%d, AR=%f "
+                                        + "was not the same",
+                                size.width, size.height, previewAspectRatio));
+                    }
+                } else {
+                    break;
+                }
+            }
+
+            if (previewSizes.isEmpty()) {
+                // Fall-back to the original faulty behavior, but at least work
+                Log.w(TAG, "mapScalerStreamConfigs - failed to find any preview size matching " +
+                        "JPEG aspect ratio " + jpegAspectRatio);
+                previewSizes = p.getSupportedPreviewSizes();
+            }
+
+            // Sort again, this time in descending order max->min
+            Collections.sort(previewSizes, Collections.reverseOrder(areaComparator));
+        }
+
         appendStreamConfig(availableStreamConfigs,
                 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes);
         appendStreamConfig(availableStreamConfigs,
@@ -279,7 +340,6 @@
             }
         }
 
-        List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
         appendStreamConfig(availableStreamConfigs,
                 HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
         /*
@@ -620,7 +680,7 @@
 
         if (thumbnailSizes != null) {
             Size[] sizes = convertSizeListToArray(thumbnailSizes);
-            Arrays.sort(sizes, new SizeAreaComparator());
+            Arrays.sort(sizes, new android.hardware.camera2.utils.SizeAreaComparator());
             m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes);
         }
     }
diff --git a/core/java/android/hardware/camera2/legacy/SizeAreaComparator.java b/core/java/android/hardware/camera2/legacy/SizeAreaComparator.java
new file mode 100644
index 0000000..75a5bab
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/SizeAreaComparator.java
@@ -0,0 +1,72 @@
+/*
+ * 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
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.hardware.Camera;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Comparator for api1 {@link Camera.Size} objects by the area.
+ *
+ * <p>This comparator totally orders by rectangle area. Tie-breaks on width.</p>
+ */
+@SuppressWarnings("deprecation")
+public class SizeAreaComparator implements Comparator<Camera.Size> {
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compare(Camera.Size size, Camera.Size size2) {
+        checkNotNull(size, "size must not be null");
+        checkNotNull(size2, "size2 must not be null");
+
+        if (size.equals(size2)) {
+            return 0;
+        }
+
+        long width = size.width;
+        long width2 = size2.width;
+        long area = width * size.height;
+        long area2 = width2 * size2.height;
+
+        if (area == area2) {
+            return (width > width2) ? 1 : -1;
+        }
+
+        return (area > area2) ? 1 : -1;
+    }
+
+    /**
+     * Get the largest api1 {@code Camera.Size} from the list by comparing each size's area
+     * by each other using {@link SizeAreaComparator}.
+     *
+     * @param sizes a non-{@code null} list of non-{@code null} sizes
+     * @return a non-{@code null} size
+     *
+     * @throws NullPointerException if {@code sizes} or any elements in it were {@code null}
+     */
+    public static Camera.Size findLargestByArea(List<Camera.Size> sizes) {
+        checkNotNull(sizes, "sizes must not be null");
+
+        return Collections.max(sizes, new SizeAreaComparator());
+    }
+}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index af53ec8..2b8b4dc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -611,6 +611,12 @@
     private final int[] mScrollOffset = new int[2];
     private final int[] mScrollConsumed = new int[2];
 
+    // Used for offsetting MotionEvents that we feed to the VelocityTracker.
+    // In the future it would be nice to be able to give this to the VelocityTracker
+    // directly, or alternatively put a VT into absolute-positioning mode that only
+    // reads the raw screen-coordinate x/y values.
+    private int mNestedYOffset = 0;
+
     // True when the popup should be hidden because of a call to
     // dispatchDisplayHint()
     private boolean mPopupHidden;
@@ -3330,6 +3336,7 @@
             scrollConsumedCorrection = mScrollConsumed[1];
             if (vtev != null) {
                 vtev.offsetLocation(0, mScrollOffset[1]);
+                mNestedYOffset += mScrollOffset[1];
             }
         }
         final int deltaY = rawDeltaY;
@@ -3399,6 +3406,7 @@
                             lastYCorrection -= mScrollOffset[1];
                             if (vtev != null) {
                                 vtev.offsetLocation(0, mScrollOffset[1]);
+                                mNestedYOffset += mScrollOffset[1];
                             }
                         } else {
                             final boolean atOverscrollEdge = overScrollBy(0, overscroll,
@@ -3582,6 +3590,10 @@
         final MotionEvent vtev = MotionEvent.obtain(ev);
 
         final int actionMasked = ev.getActionMasked();
+        if (actionMasked == MotionEvent.ACTION_DOWN) {
+            mNestedYOffset = 0;
+        }
+        vtev.offsetLocation(0, mNestedYOffset);
         switch (actionMasked) {
             case MotionEvent.ACTION_DOWN: {
                 onTouchDown(ev);
@@ -4144,7 +4156,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        int action = ev.getAction();
+        final int actionMasked = ev.getActionMasked();
         View v;
 
         if (mPositionScroller != null) {
@@ -4163,7 +4175,7 @@
             return true;
         }
 
-        switch (action & MotionEvent.ACTION_MASK) {
+        switch (actionMasked) {
         case MotionEvent.ACTION_DOWN: {
             int touchMode = mTouchMode;
             if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
@@ -4190,6 +4202,7 @@
             mLastY = Integer.MIN_VALUE;
             initOrResetVelocityTracker();
             mVelocityTracker.addMovement(ev);
+            mNestedYOffset = 0;
             startNestedScroll(SCROLL_AXIS_VERTICAL);
             if (touchMode == TOUCH_MODE_FLING) {
                 return true;
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index dd312a6..a90b392 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -142,6 +142,7 @@
      */
     private final int[] mScrollOffset = new int[2];
     private final int[] mScrollConsumed = new int[2];
+    private int mNestedYOffset;
 
     /**
      * The StrictMode "critical time span" objects to catch animation
@@ -516,6 +517,7 @@
                     mLastMotionY = y;
                     initVelocityTrackerIfNotExists();
                     mVelocityTracker.addMovement(ev);
+                    mNestedYOffset = 0;
                     if (mScrollStrictSpan == null) {
                         mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
                     }
@@ -586,9 +588,14 @@
 
         MotionEvent vtev = MotionEvent.obtain(ev);
 
-        final int action = ev.getAction();
+        final int actionMasked = ev.getActionMasked();
 
-        switch (action & MotionEvent.ACTION_MASK) {
+        if (actionMasked == MotionEvent.ACTION_DOWN) {
+            mNestedYOffset = 0;
+        }
+        vtev.offsetLocation(0, mNestedYOffset);
+
+        switch (actionMasked) {
             case MotionEvent.ACTION_DOWN: {
                 if (getChildCount() == 0) {
                     return false;
@@ -630,6 +637,7 @@
                 if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
                     deltaY -= mScrollConsumed[1];
                     vtev.offsetLocation(0, mScrollOffset[1]);
+                    mNestedYOffset += mScrollOffset[1];
                 }
                 if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
                     final ViewParent parent = getParent();
@@ -666,6 +674,7 @@
                     if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) {
                         mLastMotionY -= mScrollOffset[1];
                         vtev.offsetLocation(0, mScrollOffset[1]);
+                        mNestedYOffset += mScrollOffset[1];
                     } else if (canOverscroll) {
                         final int pulledToY = oldY + deltaY;
                         if (pulledToY < 0) {
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 4995ea1d1..a92cb74 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -3570,6 +3570,10 @@
             return mOwner != null || mRestarting;
         }
 
+        public boolean isRestarting() {
+            return mRestarting;
+        }
+
         void add(ServiceState other) {
             addDurations(other);
             mRunCount += other.mRunCount;
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_on.png b/core/res/res/drawable-hdpi/ic_notification_cast_on.png
deleted file mode 100644
index 3eaf13a..0000000
--- a/core/res/res/drawable-hdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_on.png b/core/res/res/drawable-mdpi/ic_notification_cast_on.png
deleted file mode 100644
index 42de8c4..0000000
--- a/core/res/res/drawable-mdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xhdpi/ic_notification_cast_on.png
deleted file mode 100644
index 142065b..0000000
--- a/core/res/res/drawable-xhdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png
deleted file mode 100644
index d562602..0000000
--- a/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_notification_cast_connecting.xml b/core/res/res/drawable/ic_notification_cast_connecting.xml
deleted file mode 100644
index a390bce..0000000
--- a/core/res/res/drawable/ic_notification_cast_connecting.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2013, 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.
- */
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="false">
-    <item android:drawable="@drawable/ic_notification_cast_0" android:duration="500" />
-    <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" />
-    <item android:drawable="@drawable/ic_notification_cast_2" android:duration="500" />
-    <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" />
-</animation-list>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e9c5152..5e9e497 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -405,6 +405,15 @@
     <!-- Integer indicating associated full scan max num passive channels -->
     <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels">3</integer>
 
+    <!-- Integer indicating number of association errors leading to blacklisting of the network -->
+    <integer translatable="false" name="config_wifi_framework_max_connection_errors_to_blacklist">4</integer>
+
+    <!-- Integer indicating number of authentication errors leading to blacklisting of the network -->
+    <integer translatable="false" name="config_wifi_framework_max_auth_errors_to_blacklist">4</integer>
+
+    <!-- Integer indicating minimum blacklisting delay of a wofo configuration due to connectin or auth errors -->
+    <integer translatable="false" name="config_wifi_framework_network_black_list_min_time_milli">120000</integer>
+
     <!-- Boolean indicating associated scan are allowed -->
     <bool translatable="false" name="config_wifi_framework_enable_associated_autojoin_scan">true</bool>
 
@@ -992,9 +1001,11 @@
     <!-- 2 means give warning -->
     <integer name="config_datause_notification_type">2</integer>
 
-    <!-- If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 this is the value
-         that should be used instead. A value of RIL_RADIO_TECHNOLOGY_UNKNOWN:0 means
-         there is no replacement value and VoLTE is assumed to be supported -->
+    <!-- If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 or
+         RIL_RADIO_TECHNOLOGY_UNKNOWN:0 this is the value that should be used instead.
+         A configuration value of RIL_RADIO_TECHNOLOGY_UNKNOWN:0 means
+         there is no replacement value and that the default assumption
+         for phone type (GSM) should be used. -->
     <integer name="config_volte_replacement_rat">0</integer>
 
     <!-- Flag indicating whether the current device is "voice capable".
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 50da1fa..fd4b40f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4409,17 +4409,6 @@
     <!-- Title text to append when the display is secure.  [CHAR LIMIT=30] -->
     <string name="display_manager_overlay_display_secure_suffix">, secure</string>
 
-    <!-- Title of the notification to indicate the process of connecting to a wifi display.  [CHAR LIMIT=50] -->
-    <string name="wifi_display_notification_connecting_title">Casting screen</string>
-    <!-- Message of the notification to indicate the process of connecting to a wifi display.  [CHAR LIMIT=80] -->
-    <string name="wifi_display_notification_connecting_message">Connecting to <xliff:g id="name">%1$s</xliff:g></string>
-    <!-- Title of the notification to indicate an active wifi display connection.  [CHAR LIMIT=50] -->
-    <string name="wifi_display_notification_connected_title">Casting screen</string>
-    <!-- Message of the notification to indicate an active wifi display connection.  [CHAR LIMIT=80] -->
-    <string name="wifi_display_notification_connected_message">Connected to <xliff:g id="name">%1$s</xliff:g></string>
-    <!-- Label of a button to disconnect an active wifi display connection.  [CHAR LIMIT=25] -->
-    <string name="wifi_display_notification_disconnect">Disconnect</string>
-
     <!-- Keyguard strings -->
     <!-- Label shown on emergency call button in keyguard -->
     <string name="kg_emergency_call_label">Emergency call</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c580d26..5c246a4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -330,7 +330,10 @@
   <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_tx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_rx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" />
-  <java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_network_switch_rx_packet_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_max_connection_errors_to_blacklist" />
+  <java-symbol type="integer" name="config_wifi_framework_max_auth_errors_to_blacklist" />
+  <java-symbol type="integer" name="config_wifi_framework_network_black_list_min_time_milli" />
   <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
   <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
   <java-symbol type="integer" name="config_cursorWindowSize" />
@@ -1185,8 +1188,6 @@
   <java-symbol type="drawable" name="ic_media_route_off_holo_dark" />
   <java-symbol type="drawable" name="ic_media_route_connecting_holo_dark" />
   <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
-  <java-symbol type="drawable" name="ic_notification_cast_connecting" />
-  <java-symbol type="drawable" name="ic_notification_cast_on" />
   <java-symbol type="drawable" name="cling_button" />
   <java-symbol type="drawable" name="cling_arrow_up" />
   <java-symbol type="drawable" name="cling_bg" />
@@ -1723,11 +1724,6 @@
   <java-symbol type="string" name="vpn_lockdown_error" />
   <java-symbol type="string" name="vpn_lockdown_config" />
   <java-symbol type="string" name="wallpaper_binding_label" />
-  <java-symbol type="string" name="wifi_display_notification_connecting_title" />
-  <java-symbol type="string" name="wifi_display_notification_connecting_message" />
-  <java-symbol type="string" name="wifi_display_notification_connected_title" />
-  <java-symbol type="string" name="wifi_display_notification_connected_message" />
-  <java-symbol type="string" name="wifi_display_notification_disconnect" />
   <java-symbol type="style" name="Theme.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Micro.Dialog.Alert" />
   <java-symbol type="style" name="Theme.Leanback.Dialog.Alert" />
diff --git a/data/keyboards/Vendor_0b05_Product_4500.kl b/data/keyboards/Vendor_0b05_Product_4500.kl
new file mode 100644
index 0000000..a7d519e
--- /dev/null
+++ b/data/keyboards/Vendor_0b05_Product_4500.kl
@@ -0,0 +1,42 @@
+# 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.
+
+# Asus Gamepad
+
+key 304 BUTTON_A
+key 305 BUTTON_B
+key 307 BUTTON_X
+key 308 BUTTON_Y
+key 310 BUTTON_L1
+key 311 BUTTON_R1
+key 316 BUTTON_MODE
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+key 158 BACK
+key 172 HOME
+
+axis 0x00 X
+axis 0x01 Y
+axis 0x02 Z
+axis 0x05 RZ
+axis 0x09 RTRIGGER
+axis 0x0a LTRIGGER
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+led 0x00 CONTROLLER_1
+led 0x01 CONTROLLER_2
+led 0x02 CONTROLLER_3
+led 0x03 CONTROLLER_4
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index ace5eab..bbb0b50 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -1456,12 +1456,12 @@
 
         /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
         @SuppressWarnings("unused")
-        int getStroke() {
+        int getStrokeColor() {
             return mStrokeColor;
         }
 
         @SuppressWarnings("unused")
-        void setStroke(int strokeColor) {
+        void setStrokeColor(int strokeColor) {
             mStrokeColor = strokeColor;
         }
 
@@ -1476,32 +1476,32 @@
         }
 
         @SuppressWarnings("unused")
-        float getstrokeAlpha() {
+        float getStrokeAlpha() {
             return mStrokeAlpha;
         }
 
         @SuppressWarnings("unused")
-        void setstrokeAlpha(float strokeAlpha) {
+        void setStrokeAlpha(float strokeAlpha) {
             mStrokeAlpha = strokeAlpha;
         }
 
         @SuppressWarnings("unused")
-        int getFill() {
+        int getFillColor() {
             return mFillColor;
         }
 
         @SuppressWarnings("unused")
-        void setFill(int fillColor) {
+        void setFillColor(int fillColor) {
             mFillColor = fillColor;
         }
 
         @SuppressWarnings("unused")
-        float getfillAlpha() {
+        float getFillAlpha() {
             return mFillAlpha;
         }
 
         @SuppressWarnings("unused")
-        void setfillAlpha(float fillAlpha) {
+        void setFillAlpha(float fillAlpha) {
             mFillAlpha = fillAlpha;
         }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index f779f87..eb2c920 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -125,7 +125,7 @@
         if (mLastRenderSpec == null) {
             mScheduledPreloadFirstShownPage = firstShownPage;
             mScheduledPreloadLastShownPage = lastShownPage;
-        } else {
+        } else if (mState == STATE_OPENED) {
             mRenderer.startPreload(firstShownPage, lastShownPage, mLastRenderSpec);
         }
     }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 56497d7..aa42c75 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -471,10 +471,6 @@
                 requestCreatePdfFileOrFinish();
             } break;
 
-            case STATE_PRINT_CANCELED: {
-                doFinish();
-            } break;
-
             default: {
                 updatePrintPreviewController(document.changed);
 
@@ -2393,6 +2389,7 @@
                 if (tempFile != null) {
                     tempFile.delete();
                 }
+                mFileProvider.releaseFile();
             }
         }
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index bddd691..1d629fd 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -48,6 +48,7 @@
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 67c7723..95c5020 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -317,7 +317,7 @@
                     }
                     mJustPeeked = false;
                 }
-                if (-h >= mUnlockFalsingThreshold) {
+                if (-h >= getFalsingThreshold()) {
                     mTouchAboveFalsingThreshold = true;
                 }
                 if (!mJustPeeked && (!waitForTouchSlop || mTracking) && !isTrackingBlocked()) {
@@ -370,6 +370,11 @@
         return !waitForTouchSlop || mTracking;
     }
 
+    private int getFalsingThreshold() {
+        float factor = mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+        return (int) (mUnlockFalsingThreshold * factor);
+    }
+
     protected abstract boolean hasConflictingGestures();
 
     protected void onTrackingStopped(boolean expand) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index dd947f0..71fef65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -262,6 +262,7 @@
     private StatusBarWindowManager mStatusBarWindowManager;
     private UnlockMethodCache mUnlockMethodCache;
     private DozeServiceHost mDozeServiceHost;
+    private boolean mScreenOnComingFromTouch;
 
     int mPixelFormat;
     Object mQueueLock = new Object();
@@ -2118,10 +2119,14 @@
         return mNotificationPanel.isQsExpanded();
     }
 
+    public boolean isScreenOnComingFromTouch() {
+        return mScreenOnComingFromTouch;
+    }
+
     public boolean isFalsingThresholdNeeded() {
         boolean onKeyguard = getBarState() == StatusBarState.KEYGUARD;
         boolean isMethodInsecure = mUnlockMethodCache.isMethodInsecure();
-        return onKeyguard && (isMethodInsecure || mDozing);
+        return onKeyguard && (isMethodInsecure || mDozing || mScreenOnComingFromTouch);
     }
 
     @Override  // NotificationData.Environment
@@ -3909,6 +3914,7 @@
 
     public void onScreenTurnedOff() {
         mScreenOnFromKeyguard = false;
+        mScreenOnComingFromTouch = false;
         mStackScroller.setAnimationsEnabled(false);
     }
 
@@ -4011,10 +4017,13 @@
         return !mNotificationData.getActiveNotifications().isEmpty();
     }
 
-    public void wakeUpIfDozing(long time) {
+    public void wakeUpIfDozing(long time, boolean fromTouch) {
         if (mDozing && mScrimController.isPulsing()) {
             PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
             pm.wakeUp(time);
+            if (fromTouch) {
+                mScreenOnComingFromTouch = true;
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 89ce257..4c86990 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -132,7 +132,7 @@
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_UP:
                 if (down) {
-                    mService.wakeUpIfDozing(event.getEventTime());
+                    mService.wakeUpIfDozing(event.getEventTime(), false);
                 }
         }
         if (mService.interceptMediaKey(event)) {
@@ -164,7 +164,7 @@
             intercept = mDragDownHelper.onInterceptTouchEvent(ev);
             // wake up on a touch down event, if dozing
             if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
-                mService.wakeUpIfDozing(ev.getEventTime());
+                mService.wakeUpIfDozing(ev.getEventTime(), true);
             }
         }
         if (!intercept) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 34d7cb3..1b49029 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -895,6 +895,11 @@
             while (clist.size() > 0) {
                 ConnectionRecord r = clist.get(0);
                 removeConnectionLocked(r, null, null);
+                if (clist.size() > 0 && clist.get(0) == r) {
+                    // In case it didn't get removed above, do it now.
+                    Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder);
+                    clist.remove(0);
+                }
 
                 if (r.binding.service.app != null) {
                     // This could have made the service less important.
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 7ec14c29..28e46a4 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -146,7 +146,9 @@
                         final ArrayMap<String, ProcessStats.ServiceState> services = pkg.mServices;
                         for (int isvc=services.size()-1; isvc>=0; isvc--) {
                             final ProcessStats.ServiceState service = services.valueAt(isvc);
-                            if (service.isInUse()) {
+                            if (service.isRestarting()) {
+                                service.setRestarting(true, memFactor, now);
+                            } else if (service.isInUse()) {
                                 if (service.mStartedState != ProcessStats.STATE_NOTHING) {
                                     service.setStarted(true, memFactor, now);
                                 }
@@ -157,7 +159,6 @@
                                     service.setExecuting(true, memFactor, now);
                                 }
                             }
-
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 73c9783..4dfd23b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -783,7 +783,7 @@
     int findEffectiveRootIndex() {
         int effectiveNdx = 0;
         final int topActivityNdx = mActivities.size() - 1;
-        for (int activityNdx = 0; activityNdx < topActivityNdx; ++activityNdx) {
+        for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
             final ActivityRecord r = mActivities.get(activityNdx);
             if (r.finishing) {
                 continue;
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 16554d3..683212a 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -108,8 +108,12 @@
 
     /**
      * Sets the display state, if supported.
+     *
+     * @return A runnable containing work to be deferred until after we have
+     * exited the critical section, or null if none.
      */
-    public void requestDisplayStateLocked(int state) {
+    public Runnable requestDisplayStateLocked(int state) {
+        return null;
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e609701..43c01cd 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -63,6 +63,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -214,6 +215,11 @@
     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
 
+    // Temporary list of deferred work to perform when setting the display state.
+    // Only used by requestDisplayState.  The field is self-synchronized and only
+    // intended for use inside of the requestGlobalDisplayStateInternal function.
+    private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
+
     public DisplayManagerService(Context context) {
         super(context);
         mContext = context;
@@ -318,11 +324,26 @@
     }
 
     private void requestGlobalDisplayStateInternal(int state) {
-        synchronized (mSyncRoot) {
-            if (mGlobalDisplayState != state) {
-                mGlobalDisplayState = state;
-                updateGlobalDisplayStateLocked();
-                scheduleTraversalLocked(false);
+        synchronized (mTempDisplayStateWorkQueue) {
+            try {
+                // Update the display state within the lock.
+                synchronized (mSyncRoot) {
+                    if (mGlobalDisplayState != state) {
+                        mGlobalDisplayState = state;
+                        updateGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
+                        scheduleTraversalLocked(false);
+                    }
+                }
+
+                // Setting the display power state can take hundreds of milliseconds
+                // to complete so we defer the most expensive part of the work until
+                // after we have exited the critical section to avoid blocking other
+                // threads for a long time.
+                for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
+                    mTempDisplayStateWorkQueue.get(i).run();
+                }
+            } finally {
+                mTempDisplayStateWorkQueue.clear();
             }
         }
     }
@@ -669,21 +690,25 @@
         scheduleTraversalLocked(false);
     }
 
-    private void updateGlobalDisplayStateLocked() {
+    private void updateGlobalDisplayStateLocked(List<Runnable> workQueue) {
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
             DisplayDevice device = mDisplayDevices.get(i);
-            updateDisplayStateLocked(device);
+            Runnable runnable = updateDisplayStateLocked(device);
+            if (runnable != null) {
+                workQueue.add(runnable);
+            }
         }
     }
 
-    private void updateDisplayStateLocked(DisplayDevice device) {
+    private Runnable updateDisplayStateLocked(DisplayDevice device) {
         // Blank or unblank the display immediately to match the state requested
         // by the display power controller (if known).
         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
-            device.requestDisplayStateLocked(mGlobalDisplayState);
+            return device.requestDisplayStateLocked(mGlobalDisplayState);
         }
+        return null;
     }
 
     // Adds a new logical display based on the given display device.
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 9c91ab5..24cf423 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -222,19 +222,31 @@
         }
 
         @Override
-        public void requestDisplayStateLocked(int state) {
+        public Runnable requestDisplayStateLocked(final int state) {
             if (mState != state) {
+                final int displayId = mBuiltInDisplayId;
+                final IBinder token = getDisplayTokenLocked();
                 final int mode = getPowerModeForState(state);
-                Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
-                        + Display.stateToString(state) + ", id=" + mBuiltInDisplayId + ")");
-                try {
-                    SurfaceControl.setDisplayPowerMode(getDisplayTokenLocked(), mode);
-                } finally {
-                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
-                }
                 mState = state;
                 updateDeviceInfoLocked();
+
+                // Defer actually setting the display power mode until we have exited
+                // the critical section since it can take hundreds of milliseconds
+                // to complete.
+                return new Runnable() {
+                    @Override
+                    public void run() {
+                        Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
+                                + Display.stateToString(state) + ", id=" + displayId + ")");
+                        try {
+                            SurfaceControl.setDisplayPowerMode(token, mode);
+                        } finally {
+                            Trace.traceEnd(Trace.TRACE_TAG_POWER);
+                        }
+                    }
+                };
             }
+            return null;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index a6a9a89..c2b4478 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -188,7 +188,7 @@
         }
 
         @Override
-        public void requestDisplayStateLocked(int state) {
+        public Runnable requestDisplayStateLocked(int state) {
             if (state != mDisplayState) {
                 mDisplayState = state;
                 if (state == Display.STATE_OFF) {
@@ -197,6 +197,7 @@
                     mCallback.dispatchDisplayResumed();
                 }
             }
+            return null;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 9d008b9..a17d731 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -16,18 +16,13 @@
 
 package com.android.server.display;
 
-import com.android.internal.R;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Resources;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.WifiDisplay;
 import android.hardware.display.WifiDisplaySessionInfo;
@@ -38,7 +33,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
@@ -71,17 +65,12 @@
     private static final boolean DEBUG = false;
 
     private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1;
-    private static final int MSG_UPDATE_NOTIFICATION = 2;
 
     private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT";
 
     private final WifiDisplayHandler mHandler;
     private final PersistentDataStore mPersistentDataStore;
     private final boolean mSupportsProtectedBuffers;
-    private final NotificationManager mNotificationManager;
-
-    private PendingIntent mSettingsPendingIntent;
-    private PendingIntent mDisconnectPendingIntent;
 
     private WifiDisplayController mDisplayController;
     private WifiDisplayDevice mDisplayDevice;
@@ -97,7 +86,6 @@
     private WifiDisplaySessionInfo mSessionInfo;
 
     private boolean mPendingStatusChangeBroadcast;
-    private boolean mPendingNotificationUpdate;
 
     // Called with SyncRoot lock held.
     public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -108,8 +96,6 @@
         mPersistentDataStore = persistentDataStore;
         mSupportsProtectedBuffers = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
-        mNotificationManager = (NotificationManager)context.getSystemService(
-                Context.NOTIFICATION_SERVICE);
     }
 
     @Override
@@ -125,7 +111,6 @@
         pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
         pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
         pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
-        pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate);
         pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
 
         // Try to dump the controller state.
@@ -421,13 +406,6 @@
         }
     }
 
-    private void scheduleUpdateNotificationLocked() {
-        if (!mPendingNotificationUpdate) {
-            mPendingNotificationUpdate = true;
-            mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION);
-        }
-    }
-
     // Runs on the handler.
     private void handleSendStatusChangeBroadcast() {
         final Intent intent;
@@ -447,87 +425,6 @@
         getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    // Runs on the handler.
-    private void handleUpdateNotification() {
-        final int state;
-        final WifiDisplay display;
-        synchronized (getSyncRoot()) {
-            if (!mPendingNotificationUpdate) {
-                return;
-            }
-
-            mPendingNotificationUpdate = false;
-            state = mActiveDisplayState;
-            display = mActiveDisplay;
-        }
-
-        // Cancel the old notification if there is one.
-        mNotificationManager.cancelAsUser(null,
-                R.string.wifi_display_notification_disconnect, UserHandle.ALL);
-
-        if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING
-                || state == WifiDisplayStatus.DISPLAY_STATE_CONNECTED) {
-            Context context = getContext();
-
-            // Initialize pending intents for the notification outside of the lock because
-            // creating a pending intent requires a call into the activity manager.
-            if (mSettingsPendingIntent == null) {
-                Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
-                settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
-                        | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                mSettingsPendingIntent = PendingIntent.getActivityAsUser(
-                        context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
-            }
-
-            if (mDisconnectPendingIntent == null) {
-                Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
-                mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
-                        context, 0, disconnectIntent, 0, UserHandle.CURRENT);
-            }
-
-            // Post the notification.
-            Resources r = context.getResources();
-            Notification notification;
-            if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING) {
-                notification = new Notification.Builder(context)
-                        .setContentTitle(r.getString(
-                                R.string.wifi_display_notification_connecting_title))
-                        .setContentText(r.getString(
-                                R.string.wifi_display_notification_connecting_message,
-                                display.getFriendlyDisplayName()))
-                        .setContentIntent(mSettingsPendingIntent)
-                        .setSmallIcon(R.drawable.ic_notification_cast_connecting)
-                        .setOngoing(true)
-                        .addAction(android.R.drawable.ic_menu_close_clear_cancel,
-                                r.getString(R.string.wifi_display_notification_disconnect),
-                                mDisconnectPendingIntent)
-                        .setColor(r.getColor(
-                                com.android.internal.R.color.system_notification_accent_color))
-                        .build();
-            } else {
-                notification = new Notification.Builder(context)
-                        .setContentTitle(r.getString(
-                                R.string.wifi_display_notification_connected_title))
-                        .setContentText(r.getString(
-                                R.string.wifi_display_notification_connected_message,
-                                display.getFriendlyDisplayName()))
-                        .setContentIntent(mSettingsPendingIntent)
-                        .setSmallIcon(R.drawable.ic_notification_cast_on)
-                        .setOngoing(true)
-                        .addAction(android.R.drawable.ic_menu_close_clear_cancel,
-                                r.getString(R.string.wifi_display_notification_disconnect),
-                                mDisconnectPendingIntent)
-                        .setColor(r.getColor(
-                                com.android.internal.R.color.system_notification_accent_color))
-                        .build();
-            }
-            mNotificationManager.notifyAsUser(null,
-                    R.string.wifi_display_notification_disconnect,
-                    notification, UserHandle.ALL);
-        }
-    }
-
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -605,7 +502,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
                     mActiveDisplay = display;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -618,7 +514,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
                     mActiveDisplay = null;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -636,7 +531,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
                     mActiveDisplay = display;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -659,7 +553,6 @@
                     mActiveDisplay = display;
                     renameDisplayDeviceLocked(display.getFriendlyDisplayName());
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -675,7 +568,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
                     mActiveDisplay = null;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -755,10 +647,6 @@
                 case MSG_SEND_STATUS_CHANGE_BROADCAST:
                     handleSendStatusChangeBroadcast();
                     break;
-
-                case MSG_UPDATE_NOTIFICATION:
-                    handleUpdateNotification();
-                    break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 30154d7..f456bcd 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -195,12 +195,13 @@
     }
 
     private void cancelJobsForUser(int userHandle) {
+        List<JobStatus> jobsForUser;
         synchronized (mJobs) {
-            List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
-            for (int i=0; i<jobsForUser.size(); i++) {
-                JobStatus toRemove = jobsForUser.get(i);
-                cancelJobLocked(toRemove);
-            }
+            jobsForUser = mJobs.getJobsByUser(userHandle);
+        }
+        for (int i=0; i<jobsForUser.size(); i++) {
+            JobStatus toRemove = jobsForUser.get(i);
+            cancelJobImpl(toRemove);
         }
     }
 
@@ -208,16 +209,16 @@
      * Entry point from client to cancel all jobs originating from their uid.
      * This will remove the job from the master list, and cancel the job if it was staged for
      * execution or being executed.
-     * @param uid To check against for removal of a job.
+     * @param uid Uid to check against for removal of a job.
      */
     public void cancelJobsForUid(int uid) {
-        // Remove from master list.
+        List<JobStatus> jobsForUid;
         synchronized (mJobs) {
-            List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
-            for (int i=0; i<jobsForUid.size(); i++) {
-                JobStatus toRemove = jobsForUid.get(i);
-                cancelJobLocked(toRemove);
-            }
+            jobsForUid = mJobs.getJobsByUid(uid);
+        }
+        for (int i=0; i<jobsForUid.size(); i++) {
+            JobStatus toRemove = jobsForUid.get(i);
+            cancelJobImpl(toRemove);
         }
     }
 
@@ -232,22 +233,23 @@
         JobStatus toCancel;
         synchronized (mJobs) {
             toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
-            if (toCancel != null) {
-                cancelJobLocked(toCancel);
-            }
+        }
+        if (toCancel != null) {
+            cancelJobImpl(toCancel);
         }
     }
 
-    private void cancelJobLocked(JobStatus cancelled) {
+    private void cancelJobImpl(JobStatus cancelled) {
         if (DEBUG) {
             Slog.d(TAG, "Cancelling: " + cancelled);
         }
-        // Remove from store.
         stopTrackingJob(cancelled);
-        // Remove from pending queue.
-        mPendingJobs.remove(cancelled);
-        // Cancel if running.
-        stopJobOnServiceContextLocked(cancelled);
+        synchronized (mJobs) {
+            // Remove from pending queue.
+            mPendingJobs.remove(cancelled);
+            // Cancel if running.
+            stopJobOnServiceContextLocked(cancelled);
+        }
     }
 
     /**
@@ -482,21 +484,13 @@
     // StateChangedListener implementations.
 
     /**
-     * Off-board work to our handler thread as quickly as possible, b/c this call is probably being
-     * made on the main thread.
-     * For now this takes the job and if it's ready to run it will run it. In future we might not
-     * provide the job, so that the StateChangedListener has to run through its list of jobs to
-     * see which are ready. This will further decouple the controllers from the execution logic.
+     * Posts a message to the {@link com.android.server.job.JobSchedulerService.JobHandler} that
+     * some controller's state has changed, so as to run through the list of jobs and start/stop
+     * any that are eligible.
      */
     @Override
     public void onControllerStateChanged() {
-        synchronized (mJobs) {
-            if (mReadyToRock) {
-                // Post a message to to run through the list of jobs and start/stop any that
-                // are eligible.
-                mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
-            }
-        }
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
     }
 
     @Override
@@ -512,21 +506,29 @@
 
         @Override
         public void handleMessage(Message message) {
+            synchronized (mJobs) {
+                if (!mReadyToRock) {
+                    return;
+                }
+            }
             switch (message.what) {
                 case MSG_JOB_EXPIRED:
                     synchronized (mJobs) {
                         JobStatus runNow = (JobStatus) message.obj;
                         // runNow can be null, which is a controller's way of indicating that its
                         // state is such that all ready jobs should be run immediately.
-                        if (runNow != null && !mPendingJobs.contains(runNow)) {
+                        if (runNow != null && !mPendingJobs.contains(runNow)
+                                && mJobs.containsJob(runNow)) {
                             mPendingJobs.add(runNow);
                         }
+                        queueReadyJobsForExecutionLockedH();
                     }
-                    queueReadyJobsForExecutionH();
                     break;
                 case MSG_CHECK_JOB:
-                    // Check the list of jobs and run some of them if we feel inclined.
-                    maybeQueueReadyJobsForExecutionH();
+                    synchronized (mJobs) {
+                        // Check the list of jobs and run some of them if we feel inclined.
+                        maybeQueueReadyJobsForExecutionLockedH();
+                    }
                     break;
             }
             maybeRunPendingJobsH();
@@ -538,30 +540,28 @@
          * Run through list of jobs and execute all possible - at least one is expired so we do
          * as many as we can.
          */
-        private void queueReadyJobsForExecutionH() {
-            synchronized (mJobs) {
-                ArraySet<JobStatus> jobs = mJobs.getJobs();
-                if (DEBUG) {
-                    Slog.d(TAG, "queuing all ready jobs for execution:");
-                }
-                for (int i=0; i<jobs.size(); i++) {
-                    JobStatus job = jobs.valueAt(i);
-                    if (isReadyToBeExecutedLocked(job)) {
-                        if (DEBUG) {
-                            Slog.d(TAG, "    queued " + job.toShortString());
-                        }
-                        mPendingJobs.add(job);
-                    } else if (isReadyToBeCancelledLocked(job)) {
-                        stopJobOnServiceContextLocked(job);
+        private void queueReadyJobsForExecutionLockedH() {
+            ArraySet<JobStatus> jobs = mJobs.getJobs();
+            if (DEBUG) {
+                Slog.d(TAG, "queuing all ready jobs for execution:");
+            }
+            for (int i=0; i<jobs.size(); i++) {
+                JobStatus job = jobs.valueAt(i);
+                if (isReadyToBeExecutedLocked(job)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "    queued " + job.toShortString());
                     }
+                    mPendingJobs.add(job);
+                } else if (isReadyToBeCancelledLocked(job)) {
+                    stopJobOnServiceContextLocked(job);
                 }
-                if (DEBUG) {
-                    final int queuedJobs = mPendingJobs.size();
-                    if (queuedJobs == 0) {
-                        Slog.d(TAG, "No jobs pending.");
-                    } else {
-                        Slog.d(TAG, queuedJobs + " jobs queued.");
-                    }
+            }
+            if (DEBUG) {
+                final int queuedJobs = mPendingJobs.size();
+                if (queuedJobs == 0) {
+                    Slog.d(TAG, "No jobs pending.");
+                } else {
+                    Slog.d(TAG, queuedJobs + " jobs queued.");
                 }
             }
         }
@@ -575,55 +575,53 @@
          * If more than 4 jobs total are ready we send them all off.
          * TODO: It would be nice to consolidate these sort of high-level policies somewhere.
          */
-        private void maybeQueueReadyJobsForExecutionH() {
-            synchronized (mJobs) {
-                int chargingCount = 0;
-                int idleCount =  0;
-                int backoffCount = 0;
-                int connectivityCount = 0;
-                List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
-                ArraySet<JobStatus> jobs = mJobs.getJobs();
-                for (int i=0; i<jobs.size(); i++) {
-                    JobStatus job = jobs.valueAt(i);
-                    if (isReadyToBeExecutedLocked(job)) {
-                        if (job.getNumFailures() > 0) {
-                            backoffCount++;
-                        }
-                        if (job.hasIdleConstraint()) {
-                            idleCount++;
-                        }
-                        if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
-                            connectivityCount++;
-                        }
-                        if (job.hasChargingConstraint()) {
-                            chargingCount++;
-                        }
-                        runnableJobs.add(job);
-                    } else if (isReadyToBeCancelledLocked(job)) {
-                        stopJobOnServiceContextLocked(job);
+        private void maybeQueueReadyJobsForExecutionLockedH() {
+            int chargingCount = 0;
+            int idleCount =  0;
+            int backoffCount = 0;
+            int connectivityCount = 0;
+            List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
+            ArraySet<JobStatus> jobs = mJobs.getJobs();
+            for (int i=0; i<jobs.size(); i++) {
+                JobStatus job = jobs.valueAt(i);
+                if (isReadyToBeExecutedLocked(job)) {
+                    if (job.getNumFailures() > 0) {
+                        backoffCount++;
                     }
+                    if (job.hasIdleConstraint()) {
+                        idleCount++;
+                    }
+                    if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
+                        connectivityCount++;
+                    }
+                    if (job.hasChargingConstraint()) {
+                        chargingCount++;
+                    }
+                    runnableJobs.add(job);
+                } else if (isReadyToBeCancelledLocked(job)) {
+                    stopJobOnServiceContextLocked(job);
                 }
-                if (backoffCount > 0 ||
-                        idleCount >= MIN_IDLE_COUNT ||
-                        connectivityCount >= MIN_CONNECTIVITY_COUNT ||
-                        chargingCount >= MIN_CHARGING_COUNT ||
-                        runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "maybeQueueReadyJobsForExecutionH: Running jobs.");
-                    }
-                    for (int i=0; i<runnableJobs.size(); i++) {
-                        mPendingJobs.add(runnableJobs.get(i));
-                    }
-                } else {
-                    if (DEBUG) {
-                        Slog.d(TAG, "maybeQueueReadyJobsForExecutionH: Not running anything.");
-                    }
-                }
+            }
+            if (backoffCount > 0 ||
+                    idleCount >= MIN_IDLE_COUNT ||
+                    connectivityCount >= MIN_CONNECTIVITY_COUNT ||
+                    chargingCount >= MIN_CHARGING_COUNT ||
+                    runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
                 if (DEBUG) {
-                    Slog.d(TAG, "idle=" + idleCount + " connectivity=" +
-                    connectivityCount + " charging=" + chargingCount + " tot=" +
-                            runnableJobs.size());
+                    Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Running jobs.");
                 }
+                for (int i=0; i<runnableJobs.size(); i++) {
+                    mPendingJobs.add(runnableJobs.get(i));
+                }
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Not running anything.");
+                }
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "idle=" + idleCount + " connectivity=" +
+                connectivityCount + " charging=" + chargingCount + " tot=" +
+                        runnableJobs.size());
             }
         }
 
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index df12e1a..b64c677 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -50,15 +50,9 @@
 import org.xmlpull.v1.XmlSerializer;
 
 /**
- * Maintain a list of classes, and accessor methods/logic for these jobs.
- * This class offers the following functionality:
- *     - When a job is added, it will determine if the job requirements have changed (update) and
- *       whether the controllers need to be updated.
- *     - Persists JobInfos, figures out when to to rewrite the JobInfo to disk.
- *     - Handles rescheduling of jobs.
- *       - When a periodic job is executed and must be re-added.
- *       - When a job fails and the client requests that it be retried with backoff.
- *       - This class <strong>is not</strong> thread-safe.
+ * Maintains the master list of jobs that the job scheduler is tracking. These jobs are compared by
+ * reference, so none of the functions in this class should make a copy.
+ * Also handles read/write of persisted jobs.
  *
  * Note on locking:
  *      All callers to this class must <strong>lock on the class object they are calling</strong>.
@@ -152,6 +146,10 @@
         return false;
     }
 
+    boolean containsJob(JobStatus jobStatus) {
+        return mJobSet.contains(jobStatus);
+    }
+
     public int size() {
         return mJobSet.size();
     }
@@ -180,6 +178,10 @@
         maybeWriteStatusToDiskAsync();
     }
 
+    /**
+     * @param userHandle User for whom we are querying the list of jobs.
+     * @return A list of all the jobs scheduled by the provided user. Never null.
+     */
     public List<JobStatus> getJobsByUser(int userHandle) {
         List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
         Iterator<JobStatus> it = mJobSet.iterator();
@@ -194,7 +196,7 @@
 
     /**
      * @param uid Uid of the requesting app.
-     * @return All JobStatus objects for a given uid from the master list.
+     * @return All JobStatus objects for a given uid from the master list. Never null.
      */
     public List<JobStatus> getJobsByUid(int uid) {
         List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index f1c5a6c..0198e46 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -25,6 +25,7 @@
 import com.android.internal.R;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
 
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
@@ -227,6 +228,11 @@
     private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
     private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
 
+    // TCP/IP constants.
+    // Valid TCP/UDP port range is (0, 65535].
+    private static final int TCP_MIN_PORT = 0;
+    private static final int TCP_MAX_PORT = 0xffff;
+
     // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
     private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
     // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
@@ -332,7 +338,7 @@
     // properties loaded from PROPERTIES_FILE
     private Properties mProperties;
     private String mSuplServerHost;
-    private int mSuplServerPort;
+    private int mSuplServerPort = TCP_MIN_PORT;
     private String mC2KServerHost;
     private int mC2KServerPort;
     private boolean mSuplEsEnabled = false;
@@ -487,7 +493,10 @@
                     || Intent.ACTION_SCREEN_OFF.equals(action)
                     || Intent.ACTION_SCREEN_ON.equals(action)) {
                 updateLowPowerMode();
-            } else if (action.equals(SIM_STATE_CHANGED)) {
+            } else if (action.equals(SIM_STATE_CHANGED)
+                    || action.equals(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE)
+                    || action.equals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED)) {
+                Log.d(TAG, "received SIM realted action: " + action);
                 TelephonyManager phone = (TelephonyManager)
                         mContext.getSystemService(Context.TELEPHONY_SERVICE);
                 String mccMnc = phone.getSimOperator();
@@ -497,6 +506,8 @@
                         reloadGpsProperties(context, mProperties);
                         mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
                     }
+                } else {
+                    Log.d(TAG, "SIM MCC/MNC is still not available");
                 }
             }
         }
@@ -709,6 +720,10 @@
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(SIM_STATE_CHANGED);
+        // TODO: remove the use TelephonyIntents. We are using it because SIM_STATE_CHANGED
+        // is not reliable at the moment.
+        intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE);
+        intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
     }
 
@@ -921,6 +936,11 @@
                 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
             }
         }
+        if (mSuplServerHost != null
+                && mSuplServerPort > TCP_MIN_PORT
+                && mSuplServerPort <= TCP_MAX_PORT) {
+            native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
+        }
     }
 
     /**
@@ -963,6 +983,8 @@
 
         if (enabled) {
             mSupportsXtra = native_supports_xtra();
+
+            // TODO: remove the following native calls if we can make sure they are redundant.
             if (mSuplServerHost != null) {
                 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5a94f23..a61d621 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5589,9 +5589,11 @@
         // update the package settings accordingly.
         pkg.cpuAbiOverride = cpuAbiOverride;
 
-        Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
-                + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
-                + pkg.applicationInfo.nativeLibraryRootRequiresIsa);
+        if (DEBUG_ABI_SELECTION) {
+            Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
+                    + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
+                    + pkg.applicationInfo.nativeLibraryRootRequiresIsa);
+        }
 
         // Push the derived path down into PackageSettings so we know what to
         // clean up at uninstall time.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0dadee7..4e33ca8 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2285,7 +2285,7 @@
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
                 applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                        scheme, ssp, null, null, null, userId);
+                        scheme, ssp, null, null, userId);
                 doScheme = false;
             }
             for (int iauth=0; iauth<tmpPa.countDataAuthorities(); iauth++) {
@@ -2302,7 +2302,7 @@
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
                     applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                            scheme, null, auth, path, null, userId);
+                            scheme, null, auth, path, userId);
                     doAuth = doScheme = false;
                 }
                 if (doAuth) {
@@ -2314,7 +2314,7 @@
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
                     applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                            scheme, null, auth, null, null, userId);
+                            scheme, null, auth, null, userId);
                     doScheme = false;
                 }
             }
@@ -2324,7 +2324,7 @@
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
                 applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                        scheme, null, null, null, null, userId);
+                        scheme, null, null, null, userId);
             }
             doNonData = false;
         }
@@ -2340,28 +2340,27 @@
                         builder.scheme(scheme);
                         finalIntent.setDataAndType(builder.build(), mimeType);
                         applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                                scheme, null, null, null, mimeType, userId);
+                                scheme, null, null, null, userId);
                     }
                 }
             } else {
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setType(mimeType);
                 applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                        null, null, null, null, mimeType, userId);
+                        null, null, null, null, userId);
             }
             doNonData = false;
         }
 
         if (doNonData) {
             applyDefaultPreferredActivityLPw(service, intent, flags, cn,
-                    null, null, null, null, null, userId);
+                    null, null, null, null, userId);
         }
     }
 
     private void applyDefaultPreferredActivityLPw(PackageManagerService service,
             Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
-            IntentFilter.AuthorityEntry auth, PatternMatcher path, String mimeType,
-            int userId) {
+            IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
         List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
                 intent.getType(), flags, 0);
         if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
@@ -2369,19 +2368,24 @@
         int match = 0;
         if (ri != null && ri.size() > 1) {
             boolean haveAct = false;
-            boolean haveNonSys = false;
+            ComponentName haveNonSys = null;
             ComponentName[] set = new ComponentName[ri.size()];
             for (int i=0; i<ri.size(); i++) {
                 ActivityInfo ai = ri.get(i).activityInfo;
                 set[i] = new ComponentName(ai.packageName, ai.name);
                 if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    // If any of the matches are not system apps, then
-                    // there is a third party app that is now an option...
-                    // so don't set a default since we don't want to hide it.
-                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                            + ai.packageName + "/" + ai.name + ": non-system!");
-                    haveNonSys = true;
-                    break;
+                    if (ri.get(i).match >= match) {
+                        // If any of the matches are not system apps, then
+                        // there is a third party app that is now an option...
+                        // so don't set a default since we don't want to hide it.
+                        // Only do this if the match of this one is at least as good
+                        // as what we have found as the built-in app; if it isn't
+                        // as good, the user won't want it anyway, right?
+                        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
+                                + ai.packageName + "/" + ai.name + ": non-system!");
+                        haveNonSys = set[i];
+                        break;
+                    }
                 } else if (cn.getPackageName().equals(ai.packageName)
                         && cn.getClassName().equals(ai.name)) {
                     if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
@@ -2393,7 +2397,7 @@
                             + ai.packageName + "/" + ai.name + ": skipped");
                 }
             }
-            if (haveAct && !haveNonSys) {
+            if (haveAct && haveNonSys == null) {
                 IntentFilter filter = new IntentFilter();
                 if (intent.getAction() != null) {
                     filter.addAction(intent.getAction());
@@ -2427,9 +2431,25 @@
                 }
                 PreferredActivity pa = new PreferredActivity(filter, match, set, cn, true);
                 editPreferredActivitiesLPw(userId).addFilter(pa);
-            } else if (!haveNonSys) {
-                Slog.w(TAG, "No component found for default preferred activity " + cn);
+            } else if (haveNonSys == null) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("No component ");
+                sb.append(cn.flattenToShortString());
+                sb.append(" found setting preferred ");
+                sb.append(intent);
+                sb.append("; possible matches are ");
+                for (int i=0; i<set.length; i++) {
+                    if (i > 0) sb.append(", ");
+                    sb.append(set[i].flattenToShortString());
+                }
+                Slog.w(TAG, sb.toString());
+            } else {
+                Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
+                        + haveNonSys.flattenToShortString());
             }
+        } else {
+            Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred "
+                    + cn.flattenToShortString());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8445b04..bc35330 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -11576,7 +11576,7 @@
                 final WindowList windows = getDefaultWindowListLocked();
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowState win = windows.get(winNdx);
-                    if (win.mHasSurface
+                    if (win.isVisibleLw()
                             && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
                         win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
                         // Force add to mResizingWindows.
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 402f0dd..bd64392 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -67,6 +67,7 @@
         assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size());
         final JobStatus loadedTaskStatus = jobStatusSet.iterator().next();
         assertTasksEqual(task, loadedTaskStatus.getJob());
+        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts));
         assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
                 ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
@@ -103,7 +104,8 @@
         JobStatus loaded2 = it.next();
         assertTasksEqual(task1, loaded1.getJob());
         assertTasksEqual(task2, loaded2.getJob());
-
+        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus1));
+        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus2));
         // Check that the loaded task has the correct runtimes.
         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
                 taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime());
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index fa12756..11da0f2 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -59,6 +59,10 @@
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
+            if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
+                return;
+            }
+
             switch (msg.what) {
                 case MSG_SET_IN_CALL_ADAPTER:
                     mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index 3fb547d..f31f4f2 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -30,6 +30,20 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" android:host="www.angryredplanet.com"
+                        android:pathPrefix="" />
+            </intent-filter>
+            <preferred>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" android:host="www.angryredplanet.com"
+                        android:pathPrefix="" />
+            </preferred>
         </activity>
         <activity android:name="SpamActivity" android:label="Spam!"
                 android:documentLaunchMode="always">
diff --git a/tests/VectorDrawableTest/res/anim/animation_favorite.xml b/tests/VectorDrawableTest/res/anim/animation_favorite.xml
index c81ba40..2e2d9bb 100644
--- a/tests/VectorDrawableTest/res/anim/animation_favorite.xml
+++ b/tests/VectorDrawableTest/res/anim/animation_favorite.xml
@@ -25,5 +25,35 @@
         android:valueFrom="@string/round_box"
         android:valueTo="@string/heart"
         android:valueType="pathType" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="fillAlpha"
+        android:repeatCount="-1"
+        android:valueFrom="1.0"
+        android:valueTo="0.0" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="strokeAlpha"
+        android:repeatCount="-1"
+        android:valueFrom="1.0"
+        android:valueTo="0.0" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="strokeColor"
+        android:repeatCount="-1"
+        android:valueFrom="#FF0000FF"
+        android:valueTo="#FF00FF00" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="strokeWidth"
+        android:repeatCount="-1"
+        android:valueFrom="5"
+        android:valueTo="20" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="fillColor"
+        android:repeatCount="-1"
+        android:valueFrom="#FFFF0000"
+        android:valueTo="#FF00FF00" />
 
 </set>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml b/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml
index 3bf2865..5d688cf 100644
--- a/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml
+++ b/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml
@@ -19,7 +19,7 @@
 
     <objectAnimator
         android:duration="5000"
-        android:propertyName="fill"
+        android:propertyName="fillColor"
         android:valueFrom="#FF000000"
         android:valueTo="#FFFF0000"/>
 
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 27c2541..29656c9 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -107,6 +107,12 @@
     public int autoJoinStatus;
 
     /**
+     * num IP configuration failures
+     * @hide
+     */
+    public int numIpConfigFailures;
+
+    /**
      * @hide
      * Last time we blacklisted the ScanResult
      */
@@ -256,6 +262,7 @@
             untrusted = source.untrusted;
             numConnection = source.numConnection;
             numUsage = source.numUsage;
+            numIpConfigFailures = source.numIpConfigFailures;
         }
     }
 
@@ -320,6 +327,7 @@
         dest.writeInt(untrusted ? 1 : 0);
         dest.writeInt(numConnection);
         dest.writeInt(numUsage);
+        dest.writeInt(numIpConfigFailures);
         if (informationElements != null) {
             dest.writeInt(informationElements.length);
             for (int i = 0; i < informationElements.length; i++) {
@@ -355,6 +363,7 @@
                 sr.untrusted = in.readInt() != 0;
                 sr.numConnection = in.readInt();
                 sr.numUsage = in.readInt();
+                sr.numIpConfigFailures = in.readInt();
                 int n = in.readInt();
                 if (n != 0) {
                     sr.informationElements = new InformationElement[n];
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index d27c2f7..4f5f31a 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -203,6 +203,12 @@
     public int status;
 
     /**
+     * The configuration needs to be written to networkHistory.txt
+     * @hide
+     */
+    public boolean dirty;
+
+    /**
      * The code referring to a reason for disabling the network
      * Valid when {@link #status} == Status.DISABLED
      * @hide
@@ -621,6 +627,18 @@
 
     /**
      * @hide
+     * Number of IP config failures
+     */
+    public int numIpConfigFailures;
+
+    /**
+     * @hide
+     * Number of Auth failures
+     */
+    public int numAuthFailures;
+
+    /**
+     * @hide
      * Last time we blacklisted the configuration
      */
     public long blackListTimestamp;
@@ -884,7 +902,10 @@
         }  else if (status > autoJoinStatus) {
             blackListTimestamp = System.currentTimeMillis();
         }
-        autoJoinStatus = status;
+        if (status != autoJoinStatus) {
+            autoJoinStatus = status;
+            dirty = true;
+        }
     }
 
     @Override
@@ -893,7 +914,7 @@
         if (this.status == WifiConfiguration.Status.CURRENT) {
             sbuf.append("* ");
         } else if (this.status == WifiConfiguration.Status.DISABLED) {
-            sbuf.append("- DSBLE: ").append(this.disableReason).append(" ");
+            sbuf.append("- DSBLE");
         }
         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN).
@@ -902,8 +923,20 @@
         if (this.numConnectionFailures > 0) {
             sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n");
         }
+        if (this.numIpConfigFailures > 0) {
+            sbuf.append(" numIpConfigFailures ").append(this.numIpConfigFailures).append("\n");
+        }
+        if (this.numAuthFailures > 0) {
+            sbuf.append(" numAuthFailures ").append(this.numAuthFailures).append("\n");
+        }
         if (this.autoJoinStatus > 0) {
-            sbuf.append(" autoJoinStatus ").append(this.numConnectionFailures).append("\n");
+            sbuf.append(" autoJoinStatus ").append(this.autoJoinStatus).append("\n");
+        }
+        if (this.disableReason > 0) {
+            sbuf.append(" disableReason ").append(this.disableReason).append("\n");
+        }
+        if (this.numAssociation > 0) {
+            sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
         }
         if (this.didSelfAdd) sbuf.append(" didSelfAdd");
         if (this.selfAdded) sbuf.append(" selfAdded");
@@ -1028,10 +1061,17 @@
             }
         }
         if (this.scanResultCache != null) {
-            sbuf.append("scan cache:  ");
+            sbuf.append("Scan Cache:  ");
             for(ScanResult result : this.scanResultCache.values()) {
                 sbuf.append("{").append(result.BSSID).append(",").append(result.frequency);
-                sbuf.append(",").append(result.level).append(",st=");
+                sbuf.append(",").append(result.level);
+                if (result.autoJoinStatus > 0) {
+                    sbuf.append(",st=").append(result.autoJoinStatus);
+                }
+                if (result.numIpConfigFailures > 0) {
+                    sbuf.append(",ipfail=");
+                    sbuf.append(result.numIpConfigFailures);
+                }
                 sbuf.append(result.autoJoinStatus).append("} ");
             }
             sbuf.append('\n');
@@ -1356,6 +1396,8 @@
             lastDisconnected = source.lastDisconnected;
             lastConnectionFailure = source.lastConnectionFailure;
             numConnectionFailures = source.numConnectionFailures;
+            numIpConfigFailures = source.numIpConfigFailures;
+            numAuthFailures = source.numAuthFailures;
             numScorerOverride = source.numScorerOverride;
             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
             numAssociation = source.numAssociation;
@@ -1370,6 +1412,7 @@
             autoJoinUseAggressiveJoinAttemptThreshold
                     = source.autoJoinUseAggressiveJoinAttemptThreshold;
             autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi;
+            dirty = source.dirty;
         }
     }
 
@@ -1420,6 +1463,8 @@
         dest.writeLong(blackListTimestamp);
         dest.writeLong(lastConnectionFailure);
         dest.writeInt(numConnectionFailures);
+        dest.writeInt(numIpConfigFailures);
+        dest.writeInt(numAuthFailures);
         dest.writeInt(numScorerOverride);
         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
         dest.writeInt(numAssociation);
@@ -1478,6 +1523,8 @@
                 config.blackListTimestamp = in.readLong();
                 config.lastConnectionFailure = in.readLong();
                 config.numConnectionFailures = in.readInt();
+                config.numIpConfigFailures = in.readInt();
+                config.numAuthFailures = in.readInt();
                 config.numScorerOverride = in.readInt();
                 config.numScorerOverrideAndSwitchedNetwork = in.readInt();
                 config.numAssociation = in.readInt();