Merge "Fix vertical nav button direction issue" into nyc-mr2-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 0ba937a..d4f80a0 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -60,6 +60,11 @@
      */
     public static final int APP_TRANSITION_TIMEOUT = 3;
 
+    /**
+     * Verify that calling app has access to the given provider.
+     */
+    public abstract String checkContentProviderAccess(String authority, int userId);
+
     // Called by the power manager.
     public abstract void onWakefulnessChanged(int wakefulness);
 
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e2c464..f29e576 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -200,6 +200,7 @@
             @Nullable Message cancelCallback) {
         this(context);
         mCancelable = cancelable;
+        updateWindowForCancelable();
         mCancelMessage = cancelCallback;
     }
 
@@ -207,6 +208,7 @@
             @Nullable OnCancelListener cancelListener) {
         this(context);
         mCancelable = cancelable;
+        updateWindowForCancelable();
         setOnCancelListener(cancelListener);
     }
 
@@ -1187,6 +1189,7 @@
      */
     public void setCancelable(boolean flag) {
         mCancelable = flag;
+        updateWindowForCancelable();
     }
 
     /**
@@ -1200,6 +1203,7 @@
     public void setCanceledOnTouchOutside(boolean cancel) {
         if (cancel && !mCancelable) {
             mCancelable = true;
+            updateWindowForCancelable();
         }
         
         mWindow.setCloseOnTouchOutside(cancel);
@@ -1351,4 +1355,8 @@
             }
         }
     }
+
+    private void updateWindowForCancelable() {
+        mWindow.setCloseOnSwipeEnabled(mCancelable);
+    }
 }
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 8e659e0..9e87230 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -30,7 +30,23 @@
  * @hide
  */
 public class OobData implements Parcelable {
+    private byte[] leBluetoothDeviceAddress;
     private byte[] securityManagerTk;
+    private byte[] leSecureConnectionsConfirmation;
+    private byte[] leSecureConnectionsRandom;
+
+    public byte[] getLeBluetoothDeviceAddress() {
+        return leBluetoothDeviceAddress;
+    }
+
+    /**
+     * Sets the LE Bluetooth Device Address value to be used during LE pairing.
+     * The value shall be 7 bytes. Please see Bluetooth CSSv6, Part A 1.16 for
+     * a detailed description.
+     */
+    public void setLeBluetoothDeviceAddress(byte[] leBluetoothDeviceAddress) {
+        this.leBluetoothDeviceAddress = leBluetoothDeviceAddress;
+    }
 
     public byte[] getSecurityManagerTk() {
         return securityManagerTk;
@@ -45,10 +61,29 @@
         this.securityManagerTk = securityManagerTk;
     }
 
+    public byte[] getLeSecureConnectionsConfirmation() {
+        return leSecureConnectionsConfirmation;
+    }
+
+    public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) {
+        this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation;
+    }
+
+    public byte[] getLeSecureConnectionsRandom() {
+        return leSecureConnectionsRandom;
+    }
+
+    public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) {
+        this.leSecureConnectionsRandom = leSecureConnectionsRandom;
+    }
+
     public OobData() { }
 
     private OobData(Parcel in) {
+        leBluetoothDeviceAddress = in.createByteArray();
         securityManagerTk = in.createByteArray();
+        leSecureConnectionsConfirmation = in.createByteArray();
+        leSecureConnectionsRandom = in.createByteArray();
     }
 
     public int describeContents() {
@@ -57,7 +92,10 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
+        out.writeByteArray(leBluetoothDeviceAddress);
         out.writeByteArray(securityManagerTk);
+        out.writeByteArray(leSecureConnectionsConfirmation);
+        out.writeByteArray(leSecureConnectionsRandom);
     }
 
     public static final Parcelable.Creator<OobData> CREATOR
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 4fc6b7a..6176b2c 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -21,7 +21,7 @@
 import android.os.Parcelable;
 
 /**
- * An event recorded by DnsEventListenerService.
+ * A DNS event recorded by NetdEventListenerService.
  * {@hide}
  */
 @SystemApi
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index b826584..a280e59 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -41,6 +41,8 @@
     public static final class Impl implements BaseColumns {
         private Impl() {}
 
+        public static final String AUTHORITY = "downloads";
+
         /**
          * The permission to access the download manager
          */
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 85c16b8..1cca074 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -302,6 +302,7 @@
     private boolean mDestroyed;
 
     private boolean mOverlayWithDecorCaptionEnabled = false;
+    private boolean mCloseOnSwipeEnabled = false;
 
     // The current window attributes.
     private final WindowManager.LayoutParams mWindowAttributes =
@@ -2208,4 +2209,21 @@
      * @hide
      */
     public abstract void reportActivityRelaunched();
+
+    /**
+     * Called to set flag to check if the close on swipe is enabled. This will only function if
+     * FEATURE_SWIPE_TO_DISMISS has been set.
+     * @hide
+     */
+    public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+        mCloseOnSwipeEnabled = closeOnSwipeEnabled;
+    }
+
+    /**
+     * @return {@code true} if the close on swipe is enabled.
+     * @hide
+     */
+    public boolean isCloseOnSwipeEnabled() {
+        return mCloseOnSwipeEnabled;
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 878f3a6..713190d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2495,6 +2495,7 @@
         // System.out.println("Features: 0x" + Integer.toHexString(features));
         if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
             layoutResource = R.layout.screen_swipe_dismiss;
+            setCloseOnSwipeEnabled(true);
         } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
             if (mIsFloating) {
                 TypedValue res = new TypedValue();
@@ -2566,7 +2567,7 @@
         }
 
         if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
-            registerSwipeCallbacks();
+            registerSwipeCallbacks(contentParent);
         }
 
         // Remaining setup -- of background and title -- that only applies
@@ -2980,9 +2981,12 @@
         return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
     }
 
-    private void registerSwipeCallbacks() {
-        SwipeDismissLayout swipeDismiss =
-                (SwipeDismissLayout) findViewById(R.id.content);
+    private void registerSwipeCallbacks(ViewGroup contentParent) {
+        if (!(contentParent instanceof SwipeDismissLayout)) {
+            Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
+            return;
+        }
+        SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
         swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
             @Override
             public void onDismissed(SwipeDismissLayout layout) {
@@ -3021,6 +3025,16 @@
                 });
     }
 
+    /** @hide */
+    @Override
+    public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+        if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
+                && mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
+            ((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
+        }
+        super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
+    }
+
     /**
      * Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
      * callback. This method will grab whatever extra state is needed for the
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index d88f479..31e67bd 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -110,6 +110,8 @@
 
     private float mLastX;
 
+    private boolean mDismissable = true;
+
     public SwipeDismissLayout(Context context) {
         super(context);
         init(context);
@@ -166,6 +168,10 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (!mDismissable) {
+            return super.onInterceptTouchEvent(ev);
+        }
+
         // offset because the view is translated during swipe
         ev.offsetLocation(mTranslationX, 0);
 
@@ -225,7 +231,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (mVelocityTracker == null) {
+        if (mVelocityTracker == null || !mDismissable) {
             return super.onTouchEvent(ev);
         }
         // offset because the view is translated during swipe
@@ -363,4 +369,13 @@
 
         return checkV && v.canScrollHorizontally((int) -dx);
     }
+
+    public void setDismissable(boolean dismissable) {
+        if (!dismissable && mDismissable) {
+            cancel();
+            resetMembers();
+        }
+
+        mDismissable = dismissable;
+    }
 }
diff --git a/core/res/res/layout/date_picker_material.xml b/core/res/res/layout/date_picker_material.xml
index 763f2a4..dd8a45d2 100644
--- a/core/res/res/layout/date_picker_material.xml
+++ b/core/res/res/layout/date_picker_material.xml
@@ -25,10 +25,16 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <include
-        layout="@layout/date_picker_view_animator_material"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
+    <ScrollView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fadeScrollbars="false"
+        android:scrollIndicators="top|bottom">
+        <include
+            layout="@layout/date_picker_view_animator_material"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+    </ScrollView>
 
 </LinearLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 90c19fb..a5e3fab 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -419,6 +419,9 @@
     <!-- Boolean indicating whether Hotspot 2.0/Passpoint and ANQP queries is enabled -->
     <bool translatable="false" name="config_wifi_hotspot2_enabled">false</bool>
 
+    <!-- Boolean indicating whether 802.11r Fast BSS Transition is enabled on this platform -->
+    <bool translatable="false" name="config_wifi_fast_bss_transition_enabled">false</bool>
+
     <!-- Device type information conforming to Annex B format in WiFi Direct specification.
          The default represents a dual-mode smartphone -->
     <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bbfee14..647d53a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1699,6 +1699,7 @@
   <java-symbol type="bool" name="config_wifi_background_scan_support" />
   <java-symbol type="bool" name="config_wifi_dual_band_support" />
   <java-symbol type="bool" name="config_wifi_hotspot2_enabled" />
+  <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
   <java-symbol type="color" name="config_defaultNotificationColor" />
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index c24d313..659725e 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -15,14 +15,14 @@
 package android.graphics.drawable;
 
 import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.animation.ObjectAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
@@ -55,8 +55,8 @@
 import android.view.View;
 
 import com.android.internal.R;
-
 import com.android.internal.util.VirtualRefBasePtr;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -88,9 +88,77 @@
  * <a name="VDExample"></a>
  * <li><h4>XML for the VectorDrawable containing properties to be animated</h4>
  * <p>
- * Animations can be performed on both group and path attributes, which requires groups and paths to
- * have unique names in the same VectorDrawable. Groups and paths without animations do not need to
- * be named.
+ * Animations can be performed on the animatable attributes in
+ * {@link android.graphics.drawable.VectorDrawable}. These attributes will be animated by
+ * {@link android.animation.ObjectAnimator}. The ObjectAnimator's target can be the root element,
+ * a group element or a path element. The targeted elements need to be named uniquely within
+ * the same VectorDrawable. Elements without animation do not need to be named.
+ * </p>
+ * <p>
+ * Here are all the animatable attributes in {@link android.graphics.drawable.VectorDrawable}:
+ * <table border="2" align="center" cellpadding="5">
+ *     <thead>
+ *         <tr>
+ *             <th>Element Name</th>
+ *             <th>Animatable attribute name</th>
+ *         </tr>
+ *     </thead>
+ *     <tr>
+ *         <td>&lt;vector&gt;</td>
+ *         <td>alpha</td>
+ *     </tr>
+ *     <tr>
+ *         <td rowspan="7">&lt;group&gt;</td>
+ *         <td>rotation</td>
+ *     </tr>
+ *     <tr>
+ *         <td>pivotX</td>
+ *     </tr>
+ *     <tr>
+ *         <td>pivotY</td>
+ *     </tr>
+ *     <tr>
+ *         <td>scaleX</td>
+ *     </tr>
+ *     <tr>
+ *         <td>scaleY</td>
+ *     </tr>
+ *     <tr>
+ *         <td>translateX</td>
+ *     </tr>
+ *     <tr>
+ *         <td>translateY</td>
+ *     </tr>
+ *     <tr>
+ *         <td rowspan="8">&lt;path&gt;</td>
+ *         <td>pathData</td>
+ *     </tr>
+ *     <tr>
+ *         <td>fillColor</td>
+ *     </tr>
+ *     <tr>
+ *         <td>strokeColor</td>
+ *     </tr>
+ *     <tr>
+ *         <td>strokeWidth</td>
+ *     </tr>
+ *     <tr>
+ *         <td>strokeAlpha</td>
+ *     </tr>
+ *     <tr>
+ *         <td>fillAlpha</td>
+ *     </tr>
+ *     <tr>
+ *         <td>trimPathStart</td>
+ *     </tr>
+ *     <tr>
+ *         <td>trimPathOffset</td>
+ *     </tr>
+ *     <tr>
+ *         <td>&lt;clip-path&gt;</td>
+ *         <td>pathData</td>
+ *     </tr>
+ * </table>
  * </p>
  * Below is an example of a VectorDrawable defined in vectordrawable.xml. This VectorDrawable is
  * referred to by its file name (not including file suffix) in the
@@ -118,9 +186,8 @@
  * <li><h4>XML for AnimatedVectorDrawable</h4>
  * <p>
  * An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target
- * element(s). The target elements can be the path or group to be animated. Each target element
- * contains a name attribute that references a property (of a path or a group) to animate, and an
- * animation attribute that points to an ObjectAnimator or an AnimatorSet.
+ * element(s). The target element can specify its target by android:name attribute, and link the
+ * target with the proper ObjectAnimator or AnimatorSet by android:animation attribute.
  * </p>
  * The following code sample defines an AnimatedVectorDrawable. Note that the names refer to the
  * groups and paths in the <a href="#VDExample">VectorDrawable XML above</a>.
@@ -173,7 +240,8 @@
  * merge the XML files from the previous examples into one XML file:
  * </p>
  * <pre>
- * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; &gt;
+ * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ *                  xmlns:aapt=&quothttp://schemas.android.com/aapt&quot; &gt;
  *     &lt;aapt:attr name="android:drawable"&gt;
  *         &lt;vector
  *             android:height=&quot;64dp&quot;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 1ca1552..d644bee 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -76,36 +76,27 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of this vector drawable.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:width</code></dt>
  * <dd>Used to define the intrinsic width of the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:height</code></dt>
  * <dd>Used to define the intrinsic height the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:viewportWidth</code></dt>
  * <dd>Used to define the width of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:viewportHeight</code></dt>
  * <dd>Used to define the height of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:tint</code></dt>
  * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:tintMode</code></dt>
- * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>The Porter-Duff blending mode for the tint color. Default is src_in.</dd>
  * <dt><code>android:autoMirrored</code></dt>
  * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
- * RTL (right-to-left).</dd>
- * <dd>Animatable : No.</dd>
+ * RTL (right-to-left). Default is false.</dd>
  * <dt><code>android:alpha</code></dt>
- * <dd>The opacity of this drawable.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The opacity of this drawable. Default is 1.0.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -117,32 +108,24 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the group.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:rotation</code></dt>
- * <dd>The degrees of rotation of the group.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The degrees of rotation of the group. Default is 0.</dd>
  * <dt><code>android:pivotX</code></dt>
  * <dd>The X coordinate of the pivot for the scale and rotation of the group.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * <dt><code>android:pivotY</code></dt>
  * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * <dt><code>android:scaleX</code></dt>
- * <dd>The amount of scale on the X Coordinate.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The amount of scale on the X Coordinate. Default is 1.</dd>
  * <dt><code>android:scaleY</code></dt>
- * <dd>The amount of scale on the Y coordinate.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The amount of scale on the Y coordinate. Default is 1.</dd>
  * <dt><code>android:translateX</code></dt>
  * <dd>The amount of translation on the X coordinate.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * <dt><code>android:translateY</code></dt>
  * <dd>The amount of translation on the Y coordinate.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -152,58 +135,44 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the path.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:pathData</code></dt>
  * <dd>Defines path data using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
  * <dt><code>android:fillColor</code></dt>
  * <dd>Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list
  * or a gradient color (See {@link android.R.styleable#GradientColor}
  * and {@link android.R.styleable#GradientColorItem}).
  * If this property is animated, any value set by the animation will override the original value.
  * No path fill is drawn if this property is not specified.</dd>
- * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeColor</code></dt>
  * <dd>Specifies the color used to draw the path outline. May be a color or, for SDK 24+, a color
  * state list or a gradient color (See {@link android.R.styleable#GradientColor}
  * and {@link android.R.styleable#GradientColorItem}).
  * If this property is animated, any value set by the animation will override the original value.
  * No path outline is drawn if this property is not specified.</dd>
- * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeWidth</code></dt>
- * <dd>The width a path stroke.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The width a path stroke. Default is 0.</dd>
  * <dt><code>android:strokeAlpha</code></dt>
- * <dd>The opacity of a path stroke.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The opacity of a path stroke. Default is 1.</dd>
  * <dt><code>android:fillAlpha</code></dt>
- * <dd>The opacity to fill the path with.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The opacity to fill the path with. Default is 1.</dd>
  * <dt><code>android:trimPathStart</code></dt>
- * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The fraction of the path to trim from the start, in the range from 0 to 1. Default is 0.</dd>
  * <dt><code>android:trimPathEnd</code></dt>
- * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The fraction of the path to trim from the end, in the range from 0 to 1. Default is 1.</dd>
  * <dt><code>android:trimPathOffset</code></dt>
  * <dd>Shift trim region (allows showed region to include the start and end), in the range
- * from 0 to 1.</dd>
- * <dd>Animatable : Yes.</dd>
+ * from 0 to 1. Default is 0.</dd>
  * <dt><code>android:strokeLineCap</code></dt>
- * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>Sets the linecap for a stroked path: butt, round, square. Default is butt.</dd>
  * <dt><code>android:strokeLineJoin</code></dt>
- * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd>
  * <dt><code>android:strokeMiterLimit</code></dt>
- * <dd>Sets the Miter limit for a stroked path.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd>
  * <dt><code>android:fillType</code></dt>
- * <dd>Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
- * same as SVG's "fill-rule" properties. For more details, see
+ * <dd>For SDK 24+, sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
+ * same as SVG's "fill-rule" properties. Default is nonZero. For more details, see
  * <a href="https://www.w3.org/TR/SVG/painting.html#FillRuleProperty">FillRuleProperty</a></dd>
- * <dd>Animatable : No.</dd>
  * </dl></dd>
  *
  * </dl>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4bcbea7..a332332 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -268,16 +268,16 @@
             if (cachedDevice == null) {
                 Log.w(TAG, "CachedBluetoothDevice for device " + device +
                         " not found, calling readPairedDevices().");
-                if (!readPairedDevices()) {
-                    Log.e(TAG, "Got bonding state changed for " + device +
-                            ", but we have no record of that device.");
-                    return;
+                if (readPairedDevices()) {
+                    cachedDevice = mDeviceManager.findDevice(device);
                 }
-                cachedDevice = mDeviceManager.findDevice(device);
+
                 if (cachedDevice == null) {
-                    Log.e(TAG, "Got bonding state changed for " + device +
-                            ", but device not added in cache.");
-                    return;
+                    Log.w(TAG, "Got bonding state changed for " + device +
+                            ", but we have no record of that device.");
+
+                    cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
+                    dispatchDeviceAdded(cachedDevice);
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6103355..54cd77b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -63,6 +63,8 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardStateCallback;
@@ -335,6 +337,7 @@
 
     private boolean mWakeAndUnlocking;
     private IKeyguardDrawnCallback mDrawnCallback;
+    private boolean mLockWhenSimRemoved;
 
     private boolean mIsPerUserLock;
 
@@ -429,7 +432,7 @@
                 case ABSENT:
                     // only force lock screen in case of missing sim if user hasn't
                     // gone through setup wizard
-                    synchronized (this) {
+                    synchronized (KeyguardViewMediator.this) {
                         if (shouldWaitForProvisioning()) {
                             if (!mShowing) {
                                 if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing,"
@@ -440,11 +443,12 @@
                                 resetStateLocked();
                             }
                         }
+                        onSimNotReadyLocked();
                     }
                     break;
                 case PIN_REQUIRED:
                 case PUK_REQUIRED:
-                    synchronized (this) {
+                    synchronized (KeyguardViewMediator.this) {
                         if (!mShowing) {
                             if (DEBUG_SIM_STATES) Log.d(TAG,
                                     "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
@@ -456,7 +460,7 @@
                     }
                     break;
                 case PERM_DISABLED:
-                    synchronized (this) {
+                    synchronized (KeyguardViewMediator.this) {
                         if (!mShowing) {
                             if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED and "
                                   + "keygaurd isn't showing.");
@@ -466,21 +470,40 @@
                                   + "show permanently disabled message in lockscreen.");
                             resetStateLocked();
                         }
+                        onSimNotReadyLocked();
                     }
                     break;
                 case READY:
-                    synchronized (this) {
+                    synchronized (KeyguardViewMediator.this) {
                         if (mShowing) {
                             resetStateLocked();
                         }
+                        mLockWhenSimRemoved = true;
                     }
                     break;
                 default:
-                    if (DEBUG_SIM_STATES) Log.v(TAG, "Ignoring state: " + simState);
+                    if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
+                    synchronized (KeyguardViewMediator.this) {
+                        onSimNotReadyLocked();
+                    }
                     break;
             }
         }
 
+        private void onSimNotReadyLocked() {
+            if (isSecure() && mLockWhenSimRemoved) {
+                mLockWhenSimRemoved = false;
+                MetricsLogger.action(mContext,
+                        MetricsEvent.ACTION_LOCK_BECAUSE_SIM_REMOVED, mShowing);
+                if (!mShowing) {
+                    if (DEBUG_SIM_STATES) Log.d(TAG, "SIM removed, showing keyguard");
+                    doKeyguardLocked(null);
+                } else {
+                    resetStateLocked();
+                }
+            }
+        }
+
         @Override
         public void onFingerprintAuthFailed() {
             final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 8a0dfe5..81d645e 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2213,6 +2213,14 @@
 
     // ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
 
+    // ACTION: The lockscreen gets shown because the SIM card was removed
+    // SUBTYPE: false: device was previously unlocked, true: device was previously locked
+    // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N-MR2
+    ACTION_LOCK_BECAUSE_SIM_REMOVED = 497;
+
+    // ---- End N-MR2 Constants, all N-MR2 constants go above this line ----
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 3210542..58f2074 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -12,7 +12,7 @@
     java/com/android/server/EventLogTags.logtags \
     java/com/android/server/am/EventLogTags.logtags \
     ../../../../system/netd/server/binder/android/net/INetd.aidl \
-    ../../../../system/netd/server/binder/android/net/metrics/IDnsEventListener.aidl \
+    ../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
 
 LOCAL_AIDL_INCLUDES += \
     system/netd/server/binder
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index eccfb6d..91d9ac7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -190,6 +190,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.WorkSource;
+import android.provider.Downloads;
 import android.os.storage.IMountService;
 import android.os.storage.MountServiceInternal;
 import android.os.storage.StorageManager;
@@ -8550,6 +8551,12 @@
                     // Only inspect grants matching package
                     if (packageName == null || perm.sourcePkg.equals(packageName)
                             || perm.targetPkg.equals(packageName)) {
+                        // Hacky solution as part of fixing a security bug; ignore
+                        // grants associated with DownloadManager so we don't have
+                        // to immediately launch it to regrant the permissions
+                        if (Downloads.Impl.AUTHORITY.equals(perm.uri.uri.getAuthority())
+                                && !persistable) continue;
+
                         persistChanged |= perm.revokeModes(persistable
                                 ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
 
@@ -10394,6 +10401,46 @@
     }
 
     /**
+     * Check if the calling UID has a possible chance at accessing the provider
+     * at the given authority and user.
+     */
+    public String checkContentProviderAccess(String authority, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+            userId = UserHandle.getCallingUserId();
+        }
+
+        ProviderInfo cpi = null;
+        try {
+            cpi = AppGlobals.getPackageManager().resolveContentProvider(authority,
+                    STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
+                            | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                    userId);
+        } catch (RemoteException ignored) {
+        }
+        if (cpi == null) {
+            // TODO: make this an outright failure in a future platform release;
+            // until then anonymous content notifications are unprotected
+            //return "Failed to find provider " + authority + " for user " + userId;
+            return null;
+        }
+
+        ProcessRecord r = null;
+        synchronized (mPidsSelfLocked) {
+            r = mPidsSelfLocked.get(Binder.getCallingPid());
+        }
+        if (r == null) {
+            return "Failed to find PID " + Binder.getCallingPid();
+        }
+
+        synchronized (this) {
+            return checkContentProviderPermissionLocked(cpi, r, userId, true);
+        }
+    }
+
+    /**
      * Check if {@link ProcessRecord} has a possible chance at accessing the
      * given {@link ProviderInfo}. Final permission checking is always done
      * in {@link ContentProvider}.
@@ -21849,6 +21896,11 @@
 
     private final class LocalService extends ActivityManagerInternal {
         @Override
+        public String checkContentProviderAccess(String authority, int userId) {
+            return ActivityManagerService.this.checkContentProviderAccess(authority, userId);
+        }
+
+        @Override
         public void onWakefulnessChanged(int wakefulness) {
             ActivityManagerService.this.onWakefulnessChanged(wakefulness);
         }
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index bcbcf54..28e724c 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -54,7 +54,7 @@
 
     @VisibleForTesting
     public final Impl impl = new Impl();
-    private DnsEventListenerService mDnsListener;
+    private NetdEventListenerService mNetdListener;
 
     @GuardedBy("mLock")
     private ArrayList<ConnectivityMetricsEvent> mBuffer;
@@ -77,10 +77,10 @@
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
             if (DBG) Log.d(TAG, "onBootPhase");
-            mDnsListener = new DnsEventListenerService(getContext());
+            mNetdListener = new NetdEventListenerService(getContext());
 
             publishBinderService(SERVICE_NAME, impl);
-            publishBinderService(mDnsListener.SERVICE_NAME, mDnsListener);
+            publishBinderService(mNetdListener.SERVICE_NAME, mNetdListener);
         }
     }
 
@@ -169,8 +169,8 @@
             pw.println("Buffer capacity: " + mCapacity);
             pw.println("Dropped events: " + mDropped);
         }
-        if (mDnsListener != null) {
-            mDnsListener.dump(pw);
+        if (mNetdListener != null) {
+            mNetdListener.dump(pw);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/DnsEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
similarity index 91%
rename from services/core/java/com/android/server/connectivity/DnsEventListenerService.java
rename to services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 8d206ef..21e5d3c 100644
--- a/services/core/java/com/android/server/connectivity/DnsEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -22,7 +22,7 @@
 import android.net.Network;
 import android.net.NetworkRequest;
 import android.net.metrics.DnsEvent;
-import android.net.metrics.IDnsEventListener;
+import android.net.metrics.INetdEventListener;
 import android.net.metrics.IpConnectivityLog;
 import android.util.Log;
 
@@ -37,13 +37,13 @@
 
 
 /**
- * Implementation of the IDnsEventListener interface.
+ * Implementation of the INetdEventListener interface.
  */
-public class DnsEventListenerService extends IDnsEventListener.Stub {
+public class NetdEventListenerService extends INetdEventListener.Stub {
 
-    public static final String SERVICE_NAME = "dns_listener";
+    public static final String SERVICE_NAME = "netd_listener";
 
-    private static final String TAG = DnsEventListenerService.class.getSimpleName();
+    private static final String TAG = NetdEventListenerService.class.getSimpleName();
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
@@ -110,7 +110,7 @@
     private final NetworkCallback mNetworkCallback = new NetworkCallback() {
         @Override
         public void onLost(Network network) {
-            synchronized (DnsEventListenerService.this) {
+            synchronized (NetdEventListenerService.this) {
                 DnsEventBatch batch = mEventBatches.remove(network.netId);
                 if (batch != null) {
                     batch.logAndClear();
@@ -119,12 +119,12 @@
         }
     };
 
-    public DnsEventListenerService(Context context) {
+    public NetdEventListenerService(Context context) {
         this(context.getSystemService(ConnectivityManager.class), new IpConnectivityLog());
     }
 
     @VisibleForTesting
-    public DnsEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
+    public NetdEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
         // We are started when boot is complete, so ConnectivityService should already be running.
         mCm = cm;
         mMetricsLog = log;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 0727629..2434390 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -20,12 +20,12 @@
 import android.accounts.Account;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
 import android.app.job.JobInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IContentService;
@@ -66,7 +66,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -296,24 +295,15 @@
 
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
-        final int callingUserHandle = UserHandle.getCallingUserId();
-        // Registering an observer for any user other than the calling user requires uri grant or
-        // cross user permission
-        if (callingUserHandle != userHandle) {
-            if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle)
-                    != PackageManager.PERMISSION_GRANTED) {
-                enforceCrossUserPermission(userHandle,
-                        "no permission to observe other users' provider view");
-            }
-        }
 
-        if (userHandle < 0) {
-            if (userHandle == UserHandle.USER_CURRENT) {
-                userHandle = ActivityManager.getCurrentUser();
-            } else if (userHandle != UserHandle.USER_ALL) {
-                throw new InvalidParameterException("Bad user handle for registerContentObserver: "
-                        + userHandle);
-            }
+        userHandle = handleIncomingUser(uri, pid, uid,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle);
+
+        final String msg = LocalServices.getService(ActivityManagerInternal.class)
+                .checkContentProviderAccess(uri.getAuthority(), userHandle);
+        if (msg != null) {
+            Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
+            return;
         }
 
         synchronized (mRootNode) {
@@ -363,22 +353,15 @@
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
         final int callingUserHandle = UserHandle.getCallingUserId();
-        // Notify for any user other than the caller requires uri grant or cross user permission
-        if (callingUserHandle != userHandle) {
-            if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
-                    userHandle) != PackageManager.PERMISSION_GRANTED) {
-                enforceCrossUserPermission(userHandle, "no permission to notify other users");
-            }
-        }
 
-        // We passed the permission check; resolve pseudouser targets as appropriate
-        if (userHandle < 0) {
-            if (userHandle == UserHandle.USER_CURRENT) {
-                userHandle = ActivityManager.getCurrentUser();
-            } else if (userHandle != UserHandle.USER_ALL) {
-                throw new InvalidParameterException("Bad user handle for notifyChange: "
-                        + userHandle);
-            }
+        userHandle = handleIncomingUser(uri, pid, uid,
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle);
+
+        final String msg = LocalServices.getService(ActivityManagerInternal.class)
+                .checkContentProviderAccess(uri.getAuthority(), userHandle);
+        if (msg != null) {
+            Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
+            return;
         }
 
         // This makes it so that future permission checks will be in the context of this
@@ -1143,6 +1126,27 @@
         }
     }
 
+    private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, int userId) {
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        if (userId == UserHandle.USER_ALL) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+        } else if (userId < 0) {
+            throw new IllegalArgumentException("Invalid user: " + userId);
+        } else if (userId != UserHandle.getCallingUserId()) {
+            if (checkUriPermission(uri, pid, uid, modeFlags,
+                    userId) != PackageManager.PERMISSION_GRANTED) {
+                mContext.enforceCallingOrSelfPermission(
+                        Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+            }
+        }
+
+        return userId;
+    }
+
     /**
      * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
      * permission, if the userHandle is not for the caller.
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index bdd041a..8bfa7d7 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -208,7 +208,7 @@
         mDozeScaleFactor = dozeScaleFactor;
         mNormalLightSensorRate = lightSensorRate;
         mInitialLightSensorRate = initialLightSensorRate;
-        mCurrentLightSensorRate = mNormalLightSensorRate;
+        mCurrentLightSensorRate = -1;
         mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
         mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
         mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
@@ -320,6 +320,7 @@
                 mInitialHorizonAmbientLightRingBuffer.clear();
                 mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
                 mLightSensorEnableTime = SystemClock.uptimeMillis();
+                mCurrentLightSensorRate = mInitialLightSensorRate;
                 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
                         mCurrentLightSensorRate * 1000, mHandler);
                 return true;
@@ -328,9 +329,7 @@
             if (mLightSensorEnabled) {
                 mLightSensorEnabled = false;
                 mRecentLightSamples = 0;
-                if (mInitialLightSensorRate > 0) {
-                    mCurrentLightSensorRate = mInitialLightSensorRate;
-                }
+                mCurrentLightSensorRate = -1;
                 mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
                 mSensorManager.unregisterListener(mLightSensorListener);
             }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 3207a86..de5bffd 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -315,6 +315,13 @@
                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
         int initialLightSensorRate = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
+        if (initialLightSensorRate == -1) {
+          initialLightSensorRate = lightSensorRate;
+        } else if (initialLightSensorRate > lightSensorRate) {
+          Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
+                  + initialLightSensorRate + ") to be less than or equal to "
+                  + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
+        }
         long brighteningLightDebounce = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
         long darkeningLightDebounce = resources.getInteger(
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 1f195a7..e59d69f 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -106,27 +106,31 @@
             }
             return; // Not installed, no need to restore yet.
         }
+        boolean blockRestore = false;
         if (!mPackageInfo.hasSignatures()) {
             s.wtf("Attempted to restore package " + mPackageName + ", user=" + mPackageUserId
                     + " but signatures not found in the restore data.");
+            blockRestore = true;
+        }
+        if (!blockRestore) {
+            final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
+            if (!mPackageInfo.canRestoreTo(s, pi)) {
+                // Package is now installed, but can't restore.  Let the subclass do the cleanup.
+                blockRestore = true;
+            }
+        }
+        if (blockRestore) {
             onRestoreBlocked();
-            return;
+        } else {
+            if (ShortcutService.DEBUG) {
+                Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
+                        mPackageUserId, getOwnerUserId()));
+            }
+
+            onRestored();
         }
 
-        final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
-        if (!mPackageInfo.canRestoreTo(s, pi)) {
-            // Package is now installed, but can't restore.  Let the subclass do the cleanup.
-            onRestoreBlocked();
-            return;
-        }
-        if (ShortcutService.DEBUG) {
-            Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
-                    mPackageUserId, getOwnerUserId()));
-        }
-
-        onRestored();
-
-        // Now the package is not shadow.
+        // Either way, it's no longer a shadow.
         mPackageInfo.setShadow(false);
 
         s.scheduleSaveUser(mPackageUserId);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 500af0c..6e8799e 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -3739,6 +3739,16 @@
         }
     }
 
+    @VisibleForTesting
+    ShortcutLauncher getLauncherShortcutForTest(String packageName, int userId) {
+        synchronized (mLock) {
+            final ShortcutUser user = mUsers.get(userId);
+            if (user == null) return null;
+
+            return user.getAllLaunchersForTest().get(PackageWithUser.of(userId, packageName));
+        }
+    }
+
     /**
      * Control whether {@link #verifyStates} should be performed.  We always perform it during unit
      * tests.
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
similarity index 91%
rename from services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 033b2c9..63d5d9fb 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -20,7 +20,7 @@
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.metrics.DnsEvent;
-import android.net.metrics.IDnsEventListener;
+import android.net.metrics.INetdEventListener;
 import android.net.metrics.IpConnectivityLog;
 
 import junit.framework.TestCase;
@@ -47,12 +47,12 @@
 import java.util.OptionalInt;
 import java.util.stream.IntStream;
 
-public class DnsEventListenerServiceTest extends TestCase {
+public class NetdEventListenerServiceTest extends TestCase {
 
-    // TODO: read from DnsEventListenerService after this constant is read from system property
+    // TODO: read from NetdEventListenerService after this constant is read from system property
     static final int BATCH_SIZE = 100;
-    static final int EVENT_TYPE = IDnsEventListener.EVENT_GETADDRINFO;
-    // TODO: read from IDnsEventListener
+    static final int EVENT_TYPE = INetdEventListener.EVENT_GETADDRINFO;
+    // TODO: read from INetdEventListener
     static final int RETURN_CODE = 1;
 
     static final byte[] EVENT_TYPES  = new byte[BATCH_SIZE];
@@ -66,7 +66,7 @@
         }
     }
 
-    DnsEventListenerService mDnsService;
+    NetdEventListenerService mNetdEventListenerService;
 
     @Mock ConnectivityManager mCm;
     @Mock IpConnectivityLog mLog;
@@ -77,7 +77,7 @@
         MockitoAnnotations.initMocks(this);
         mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
         mEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
-        mDnsService = new DnsEventListenerService(mCm, mLog);
+        mNetdEventListenerService = new NetdEventListenerService(mCm, mLog);
 
         verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
     }
@@ -131,7 +131,7 @@
         new Thread() {
             public void run() {
                 while (System.currentTimeMillis() < stop) {
-                    mDnsService.dump(pw);
+                    mNetdEventListenerService.dump(pw);
                 }
             }
         }.start();
@@ -158,7 +158,7 @@
 
     void log(int netId, int[] latencies) {
         for (int l : latencies) {
-            mDnsService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
+            mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 3cfdc32..cd48f36 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -4938,6 +4938,9 @@
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
+        assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+                .getPackageInfo().isShadow());
+
 
         installPackage(USER_0, CALLING_PACKAGE_2);
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
@@ -4946,6 +4949,8 @@
                     mManager.getPinnedShortcuts()),
                     "s1", "s2", "s3");
         });
+        assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, USER_0)
+                .getPackageInfo().isShadow());
 
         installPackage(USER_0, LAUNCHER_1);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
@@ -5069,6 +5074,8 @@
                     mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
                     /* empty */);
         });
+        assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+                .getPackageInfo().isShadow());
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -5091,6 +5098,8 @@
                     mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
                     /* empty */);
         });
+        assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_2, USER_0)
+                .getPackageInfo().isShadow());
 
         installPackage(USER_0, CALLING_PACKAGE_3);
         runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 62625bd..58c5002 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -324,6 +324,7 @@
         private final PhoneAccountHandle mAccountHandle;
         private final int mCallCapabilities;
         private final int mCallProperties;
+        private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
         private final DisconnectCause mDisconnectCause;
         private final long mConnectTimeMillis;
         private final GatewayInfo mGatewayInfo;
@@ -536,6 +537,15 @@
         }
 
         /**
+         * @return a bitmask of the audio routes available for the call.
+         *
+         * @hide
+         */
+        public int getSupportedAudioRoutes() {
+            return mSupportedAudioRoutes;
+        }
+
+        /**
          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
          * by {@link android.telecom.DisconnectCause}.
          */
diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java
index 2b16722..f601d8b 100644
--- a/telecomm/java/android/telecom/CallAudioState.java
+++ b/telecomm/java/android/telecom/CallAudioState.java
@@ -44,8 +44,12 @@
      */
     public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
 
-    /** Bit mask of all possible audio routes. */
-    private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
+    /**
+     * Bit mask of all possible audio routes.
+     *
+     * @hide
+     **/
+    public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
             ROUTE_SPEAKER;
 
     private final boolean isMuted;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 8f9c758..6cf9828 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -722,6 +722,7 @@
         public void onDestroyed(Connection c) {}
         public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {}
         public void onConnectionPropertiesChanged(Connection c, int properties) {}
+        public void onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes) {}
         public void onVideoProviderChanged(
                 Connection c, VideoProvider videoProvider) {}
         public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
@@ -1428,6 +1429,7 @@
     private boolean mRingbackRequested = false;
     private int mConnectionCapabilities;
     private int mConnectionProperties;
+    private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
     private VideoProvider mVideoProvider;
     private boolean mAudioModeIsVoip;
     private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
@@ -1708,6 +1710,15 @@
     }
 
     /**
+     * Returns the connection's supported audio routes.
+     *
+     * @hide
+     */
+    public final int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
+    /**
      * Sets the value of the {@link #getAddress()} property.
      *
      * @param address The new address.
@@ -1929,6 +1940,28 @@
     }
 
     /**
+     * Sets the supported audio routes.
+     *
+     * @param supportedAudioRoutes the supported audio routes as a bitmask.
+     *                             See {@link CallAudioState}
+     * @hide
+     */
+    public final void setSupportedAudioRoutes(int supportedAudioRoutes) {
+        if ((supportedAudioRoutes
+                & (CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER)) == 0) {
+            throw new IllegalArgumentException(
+                    "supported audio routes must include either speaker or earpiece");
+        }
+
+        if (mSupportedAudioRoutes != supportedAudioRoutes) {
+            mSupportedAudioRoutes = supportedAudioRoutes;
+            for (Listener l : mListeners) {
+                l.onSupportedAudioRoutesChanged(this, mSupportedAudioRoutes);
+            }
+        }
+    }
+
+    /**
      * Tears down the Connection object.
      */
     public final void destroy() {
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index dd55ca9..f782232 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -776,6 +776,7 @@
                         connection.getState(),
                         connection.getConnectionCapabilities(),
                         connection.getConnectionProperties(),
+                        connection.getSupportedAudioRoutes(),
                         connection.getAddress(),
                         connection.getAddressPresentation(),
                         connection.getCallerDisplayName(),
@@ -1175,6 +1176,7 @@
                     connection.getState(),
                     connection.getConnectionCapabilities(),
                     connection.getConnectionProperties(),
+                    connection.getSupportedAudioRoutes(),
                     connection.getAddress(),
                     connection.getAddressPresentation(),
                     connection.getCallerDisplayName(),
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 4a6fd7c..f7a6595 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -39,6 +39,7 @@
     private final List<String> mCannedSmsResponses;
     private final int mCapabilities;
     private final int mProperties;
+    private final int mSupportedAudioRoutes;
     private final long mConnectTimeMillis;
     private final Uri mHandle;
     private final int mHandlePresentation;
@@ -64,6 +65,7 @@
             List<String> cannedSmsResponses,
             int capabilities,
             int properties,
+            int supportedAudioRoutes,
             long connectTimeMillis,
             Uri handle,
             int handlePresentation,
@@ -86,6 +88,7 @@
         mCannedSmsResponses = cannedSmsResponses;
         mCapabilities = capabilities;
         mProperties = properties;
+        mSupportedAudioRoutes = supportedAudioRoutes;
         mConnectTimeMillis = connectTimeMillis;
         mHandle = handle;
         mHandlePresentation = handlePresentation;
@@ -137,6 +140,11 @@
     /** Bitmask of properties of the call. */
     public int getProperties() { return mProperties; }
 
+    /** Bitmask of supported routes of the call */
+    public int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
     /** The time that the call switched to the active state. */
     public long getConnectTimeMillis() {
         return mConnectTimeMillis;
@@ -292,6 +300,7 @@
             source.readList(conferenceableCallIds, classLoader);
             Bundle intentExtras = source.readBundle(classLoader);
             Bundle extras = source.readBundle(classLoader);
+            int supportedAudioRoutes = source.readInt();
             return new ParcelableCall(
                     id,
                     state,
@@ -299,6 +308,7 @@
                     cannedSmsResponses,
                     capabilities,
                     properties,
+                    supportedAudioRoutes,
                     connectTimeMillis,
                     handle,
                     handlePresentation,
@@ -355,6 +365,7 @@
         destination.writeList(mConferenceableCallIds);
         destination.writeBundle(mIntentExtras);
         destination.writeBundle(mExtras);
+        destination.writeInt(mSupportedAudioRoutes);
     }
 
     @Override
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index 540f388..e9dba68 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -37,6 +37,7 @@
     private final int mState;
     private final int mConnectionCapabilities;
     private final int mConnectionProperties;
+    private final int mSupportedAudioRoutes;
     private final Uri mAddress;
     private final int mAddressPresentation;
     private final String mCallerDisplayName;
@@ -57,6 +58,7 @@
             int state,
             int capabilities,
             int properties,
+            int supportedAudioRoutes,
             Uri address,
             int addressPresentation,
             String callerDisplayName,
@@ -74,6 +76,7 @@
         mState = state;
         mConnectionCapabilities = capabilities;
         mConnectionProperties = properties;
+        mSupportedAudioRoutes = supportedAudioRoutes;
         mAddress = address;
         mAddressPresentation = addressPresentation;
         mCallerDisplayName = callerDisplayName;
@@ -117,6 +120,10 @@
         return mConnectionProperties;
     }
 
+    public int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
     public Uri getHandle() {
         return mAddress;
     }
@@ -210,12 +217,14 @@
             source.readStringList(conferenceableConnectionIds);
             Bundle extras = Bundle.setDefusable(source.readBundle(classLoader), true);
             int properties = source.readInt();
+            int supportedAudioRoutes = source.readInt();
 
             return new ParcelableConnection(
                     phoneAccount,
                     state,
                     capabilities,
                     properties,
+                    supportedAudioRoutes,
                     address,
                     addressPresentation,
                     callerDisplayName,
@@ -264,5 +273,6 @@
         destination.writeStringList(mConferenceableConnectionIds);
         destination.writeBundle(mExtras);
         destination.writeInt(mConnectionProperties);
+        destination.writeInt(mSupportedAudioRoutes);
     }
 }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 473e394..692dfb73 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -17,15 +17,6 @@
 package android.telecom;
 
 import android.annotation.SystemApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
@@ -37,7 +28,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.MissingResourceException;
 
 /**
  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
@@ -217,6 +207,7 @@
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
     private final List<String> mSupportedUriSchemes;
+    private final int mSupportedAudioRoutes;
     private final Icon mIcon;
     private final Bundle mExtras;
     private boolean mIsEnabled;
@@ -226,10 +217,12 @@
      * Helper class for creating a {@link PhoneAccount}.
      */
     public static class Builder {
+
         private PhoneAccountHandle mAccountHandle;
         private Uri mAddress;
         private Uri mSubscriptionAddress;
         private int mCapabilities;
+        private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
@@ -266,6 +259,7 @@
             mIsEnabled = phoneAccount.isEnabled();
             mExtras = phoneAccount.getExtras();
             mGroupId = phoneAccount.getGroupId();
+            mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
         }
 
         /**
@@ -411,6 +405,18 @@
         }
 
         /**
+         * Sets the audio routes supported by this {@link PhoneAccount}.
+         *
+         * @param routes bit mask of available routes.
+         * @return The builder.
+         * @hide
+         */
+        public Builder setSupportedAudioRoutes(int routes) {
+            mSupportedAudioRoutes = routes;
+            return this;
+        }
+
+        /**
          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
          *
          * @return The {@link PhoneAccount}.
@@ -432,6 +438,7 @@
                     mShortDescription,
                     mSupportedUriSchemes,
                     mExtras,
+                    mSupportedAudioRoutes,
                     mIsEnabled,
                     mGroupId);
         }
@@ -448,6 +455,7 @@
             CharSequence shortDescription,
             List<String> supportedUriSchemes,
             Bundle extras,
+            int supportedAudioRoutes,
             boolean isEnabled,
             String groupId) {
         mAccountHandle = account;
@@ -460,6 +468,7 @@
         mShortDescription = shortDescription;
         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
         mExtras = extras;
+        mSupportedAudioRoutes = supportedAudioRoutes;
         mIsEnabled = isEnabled;
         mGroupId = groupId;
     }
@@ -533,6 +542,17 @@
     }
 
     /**
+     * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask.
+     *
+     * @param route The routes to check.
+     * @return {@code true} if the phone account has the routes.
+     * @hide
+     */
+    public boolean hasAudioRoutes(int routes) {
+        return (mSupportedAudioRoutes & routes) == routes;
+    }
+
+    /**
      * A short label describing a {@code PhoneAccount}.
      *
      * @return A label for this {@code PhoneAccount}.
@@ -572,6 +592,15 @@
     }
 
     /**
+     * The audio routes supported by this {@code PhoneAccount}.
+     *
+     * @hide
+     */
+    public int getSupportedAudioRoutes() {
+        return mSupportedAudioRoutes;
+    }
+
+    /**
      * The icon to represent this {@code PhoneAccount}.
      *
      * @return The icon.
@@ -687,6 +716,7 @@
         out.writeByte((byte) (mIsEnabled ? 1 : 0));
         out.writeBundle(mExtras);
         out.writeString(mGroupId);
+        out.writeInt(mSupportedAudioRoutes);
     }
 
     public static final Creator<PhoneAccount> CREATOR
@@ -731,6 +761,7 @@
         mIsEnabled = in.readByte() == 1;
         mExtras = in.readBundle();
         mGroupId = in.readString();
+        mSupportedAudioRoutes = in.readInt();
     }
 
     @Override
@@ -740,7 +771,9 @@
                 .append("] PhoneAccount: ")
                 .append(mAccountHandle)
                 .append(" Capabilities: ")
-                .append(capabilitiesToString(mCapabilities))
+                .append(capabilitiesToString())
+                .append(" Audio Routes: ")
+                .append(audioRoutesToString())
                 .append(" Schemes: ");
         for (String scheme : mSupportedUriSchemes) {
             sb.append(scheme)
@@ -760,7 +793,7 @@
      * @param capabilities The capabilities bitmask.
      * @return String representation of the capabilities bitmask.
      */
-    private String capabilitiesToString(int capabilities) {
+    private String capabilitiesToString() {
         StringBuilder sb = new StringBuilder();
         if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
             sb.append("Video ");
@@ -794,4 +827,23 @@
         }
         return sb.toString();
     }
+
+    private String audioRoutesToString() {
+        StringBuilder sb = new StringBuilder();
+
+        if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) {
+            sb.append("B");
+        }
+        if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) {
+            sb.append("E");
+        }
+        if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) {
+            sb.append("S");
+        }
+        if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) {
+            sb.append("W");
+        }
+
+        return sb.toString();
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index d3d5ea0..f123980 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -98,10 +98,22 @@
          */
         public static final int OSEN = 5;
 
+        /**
+         * IEEE 802.11r Fast BSS Transition with PSK authentication.
+         * @hide
+         */
+        public static final int FT_PSK = 6;
+
+        /**
+         * IEEE 802.11r Fast BSS Transition with EAP authentication.
+         * @hide
+         */
+        public static final int FT_EAP = 7;
+
         public static final String varName = "key_mgmt";
 
         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
-                "WPA2_PSK", "OSEN" };
+                "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
     }
 
     /**