Merge "Fix pinned slices returning different Uris." into pi-dev
diff --git a/api/current.txt b/api/current.txt
index eac2168..dc0802d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -41685,10 +41685,7 @@
     field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
     field public static final java.lang.String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
     field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
-    field public static final java.lang.String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
     field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
-    field public static final java.lang.String KEY_DATA_RAPID_NOTIFICATION_BOOL = "data_rapid_notification_bool";
-    field public static final java.lang.String KEY_DATA_WARNING_NOTIFICATION_BOOL = "data_warning_notification_bool";
     field public static final java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index 685759f..871226b 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -42,6 +42,7 @@
 const std::string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff";  // -1
 const std::string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff";                  // -1
 const std::string MESSAGE_FIELD_5 = "\x2a\x10" + VARINT_FIELD_1 + STRING_FIELD_2;
+const std::string NEGATIVE_VARINT_FIELD_6 = "\x30\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01";  // -1
 
 class PrivacyBufferTest : public Test {
 public:
@@ -161,6 +162,11 @@
     assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(5, MESSAGE_TYPE, DEST_LOCAL));
 }
 
+TEST_F(PrivacyBufferTest, StripNegativeVarint) {
+    writeToFdBuffer(NEGATIVE_VARINT_FIELD_6);
+    assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(6, OTHER_TYPE, DEST_LOCAL));
+}
+
 TEST_F(PrivacyBufferTest, NoStripVarintField) {
     writeToFdBuffer(VARINT_FIELD_1);
     assertStripByFields(DEST_EXPLICIT, VARINT_FIELD_1, 1,
@@ -191,6 +197,12 @@
                         create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC));
 }
 
+TEST_F(PrivacyBufferTest, NoStripNegativeVarintField) {
+    writeToFdBuffer(NEGATIVE_VARINT_FIELD_6);
+    assertStripByFields(DEST_EXPLICIT, NEGATIVE_VARINT_FIELD_6, 1,
+                        create_privacy(6, OTHER_TYPE, DEST_AUTOMATIC));
+}
+
 TEST_F(PrivacyBufferTest, StripVarintAndString) {
     writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3 +
                     FIX32_FIELD_4);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 81c9b6b..9ac54b9 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -994,6 +994,7 @@
 Landroid/media/AudioAttributes;->mFormattedTags:Ljava/lang/String;
 Landroid/media/AudioAttributes;->mSource:I
 Landroid/media/AudioAttributes;->mUsage:I
+Landroid/media/AudioAttributes$Builder;->addTag(Ljava/lang/String;)Landroid/media/AudioAttributes$Builder;
 Landroid/media/AudioDevicePortConfig;-><init>(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V
 Landroid/media/AudioDevicePort;-><init>(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V
 Landroid/media/AudioFormat;-><init>(IIII)V
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 5461c0c..0f2a11a 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -86,6 +86,7 @@
     ParceledListSlice getNotificationChannelGroups(String pkg);
     boolean onlyHasDefaultChannel(String pkg, int uid);
     ParceledListSlice getRecentNotifyingAppsForUser(int userId);
+    int getBlockedAppCount(int userId);
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2b4f420..8ee443b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3115,7 +3115,6 @@
         private int mTextColorsAreForBackground = COLOR_INVALID;
         private int mPrimaryTextColor = COLOR_INVALID;
         private int mSecondaryTextColor = COLOR_INVALID;
-        private int mActionBarColor = COLOR_INVALID;
         private int mBackgroundColor = COLOR_INVALID;
         private int mForegroundColor = COLOR_INVALID;
         /**
@@ -4359,16 +4358,6 @@
             return mSecondaryTextColor;
         }
 
-        private int getActionBarColor() {
-            ensureColors();
-            return mActionBarColor;
-        }
-
-        private int getActionBarColorDeEmphasized() {
-            int backgroundColor = getBackgroundColor();
-            return NotificationColorUtil.getShiftedColor(backgroundColor, 12);
-        }
-
         private void setTextViewColorSecondary(RemoteViews contentView, int id) {
             ensureColors();
             contentView.setTextColor(id, mSecondaryTextColor);
@@ -4378,7 +4367,6 @@
             int backgroundColor = getBackgroundColor();
             if (mPrimaryTextColor == COLOR_INVALID
                     || mSecondaryTextColor == COLOR_INVALID
-                    || mActionBarColor == COLOR_INVALID
                     || mTextColorsAreForBackground != backgroundColor) {
                 mTextColorsAreForBackground = backgroundColor;
                 if (!hasForegroundColor() || !isColorized()) {
@@ -4451,8 +4439,6 @@
                         }
                     }
                 }
-                mActionBarColor = NotificationColorUtil.resolveActionBarColor(mContext,
-                        backgroundColor);
             }
         }
 
@@ -4769,8 +4755,8 @@
                     validRemoteInput |= actionHasValidInput;
 
                     final RemoteViews button = generateActionButton(action, emphazisedMode,
-                            i % 2 != 0, p.ambient);
-                    if (actionHasValidInput) {
+                            p.ambient);
+                    if (actionHasValidInput && !emphazisedMode) {
                         // Clear the drawable
                         button.setInt(R.id.action0, "setBackgroundResource", 0);
                     }
@@ -5077,7 +5063,7 @@
         }
 
         private RemoteViews generateActionButton(Action action, boolean emphazisedMode,
-                boolean oddAction, boolean ambient) {
+                boolean ambient) {
             final boolean tombstone = (action.actionIntent == null);
             RemoteViews button = new BuilderRemoteViews(mContext.getApplicationInfo(),
                     emphazisedMode ? getEmphasizedActionLayoutResource()
@@ -5090,35 +5076,42 @@
             if (action.mRemoteInputs != null) {
                 button.setRemoteInputs(R.id.action0, action.mRemoteInputs);
             }
-            // TODO: handle emphasized mode / actions right
             if (emphazisedMode) {
                 // change the background bgColor
-                int bgColor;
-                if (isColorized()) {
-                    bgColor = oddAction ? getActionBarColor() : getActionBarColorDeEmphasized();
-                } else {
-                    bgColor = mContext.getColor(oddAction ? R.color.notification_action_list
-                            : R.color.notification_action_list_dark);
-                }
-                button.setDrawableTint(R.id.button_holder, true,
-                        bgColor, PorterDuff.Mode.SRC_ATOP);
                 CharSequence title = action.title;
                 ColorStateList[] outResultColor = null;
+                int background = resolveBackgroundColor();
                 if (isLegacy()) {
                     title = NotificationColorUtil.clearColorSpans(title);
                 } else {
                     outResultColor = new ColorStateList[1];
-                    title = ensureColorSpanContrast(title, bgColor, outResultColor);
+                    title = ensureColorSpanContrast(title, background, outResultColor);
                 }
                 button.setTextViewText(R.id.action0, processTextSpans(title));
                 setTextViewColorPrimary(button, R.id.action0);
-                if (outResultColor != null && outResultColor[0] != null) {
-                    // We need to set the text color as well since changing a text to uppercase
-                    // clears its spans.
-                    button.setTextColor(R.id.action0, outResultColor[0]);
+                int rippleColor;
+                boolean hasColorOverride = outResultColor != null && outResultColor[0] != null;
+                if (hasColorOverride) {
+                    // There's a span spanning the full text, let's take it and use it as the
+                    // background color
+                    background = outResultColor[0].getDefaultColor();
+                    int textColor = NotificationColorUtil.resolvePrimaryColor(mContext,
+                            background);
+                    button.setTextColor(R.id.action0, textColor);
+                    rippleColor = textColor;
                 } else if (mN.color != COLOR_DEFAULT && !isColorized() && mTintActionButtons) {
-                    button.setTextColor(R.id.action0,resolveContrastColor());
+                    rippleColor = resolveContrastColor();
+                    button.setTextColor(R.id.action0, rippleColor);
+                } else {
+                    rippleColor = getPrimaryTextColor();
                 }
+                // We only want about 20% alpha for the ripple
+                rippleColor = (rippleColor & 0x00ffffff) | 0x33000000;
+                button.setColorStateList(R.id.action0, "setRippleColor",
+                        ColorStateList.valueOf(rippleColor));
+                button.setColorStateList(R.id.action0, "setButtonBackground",
+                        ColorStateList.valueOf(background));
+                button.setBoolean(R.id.action0, "setHasStroke", !hasColorOverride);
             } else {
                 button.setTextViewText(R.id.action0, processTextSpans(
                         processLegacyText(action.title)));
@@ -5168,31 +5161,35 @@
                             }
                             textColor = new ColorStateList(textColor.getStates().clone(),
                                     newColors);
+                            if (fullLength) {
+                                outResultColor[0] = textColor;
+                                // Let's drop the color from the span
+                                textColor = null;
+                            }
                             resultSpan = new TextAppearanceSpan(
                                     originalSpan.getFamily(),
                                     originalSpan.getTextStyle(),
                                     originalSpan.getTextSize(),
                                     textColor,
                                     originalSpan.getLinkTextColor());
-                            if (fullLength) {
-                                outResultColor[0] = new ColorStateList(
-                                        textColor.getStates().clone(), newColors);
-                            }
                         }
                     } else if (resultSpan instanceof ForegroundColorSpan) {
                         ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
                         int foregroundColor = originalSpan.getForegroundColor();
                         foregroundColor = NotificationColorUtil.ensureLargeTextContrast(
                                 foregroundColor, background, mInNightMode);
-                        resultSpan = new ForegroundColorSpan(foregroundColor);
                         if (fullLength) {
                             outResultColor[0] = ColorStateList.valueOf(foregroundColor);
+                            resultSpan = null;
+                        } else {
+                            resultSpan = new ForegroundColorSpan(foregroundColor);
                         }
                     } else {
                         resultSpan = span;
                     }
-
-                    builder.setSpan(resultSpan, spanStart, spanEnd, ss.getSpanFlags(span));
+                    if (resultSpan != null) {
+                        builder.setSpan(resultSpan, spanStart, spanEnd, ss.getSpanFlags(span));
+                    }
                 }
                 return builder;
             }
@@ -5523,6 +5520,18 @@
             }
         }
 
+        /**
+         * Same as getBackgroundColor but also resolved the default color to the background.
+         */
+        private int resolveBackgroundColor() {
+            int backgroundColor = getBackgroundColor();
+            if (backgroundColor == COLOR_DEFAULT) {
+                backgroundColor = mContext.getColor(
+                        com.android.internal.R.color.notification_material_background_color);
+            }
+            return backgroundColor;
+        }
+
         private boolean isColorized() {
             return mN.isColorized();
         }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 3df4336..71edc8a 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -1514,22 +1514,24 @@
      * @return true, if the request is send to the Bluetooth stack.
      * @hide
      */
-    public boolean requestLeConnectionUpdate(int minConnectionInterval,
-                                                 int maxConnectionInterval,
-                                                 int slaveLatency, int supervisionTimeout) {
+    public boolean requestLeConnectionUpdate(int minConnectionInterval, int maxConnectionInterval,
+                                             int slaveLatency, int supervisionTimeout,
+                                             int minConnectionEventLen, int maxConnectionEventLen) {
         if (DBG) {
             Log.d(TAG, "requestLeConnectionUpdate() - min=(" + minConnectionInterval
-                       + ")" + (1.25 * minConnectionInterval)
-                       + "msec, max=(" + maxConnectionInterval + ")"
+                        + ")" + (1.25 * minConnectionInterval)
+                        + "msec, max=(" + maxConnectionInterval + ")"
                         + (1.25 * maxConnectionInterval) + "msec, latency=" + slaveLatency
-                       + ", timeout=" + supervisionTimeout + "msec");
+                        + ", timeout=" + supervisionTimeout + "msec" + ", min_ce="
+                        + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen);
         }
         if (mService == null || mClientIf == 0) return false;
 
         try {
             mService.leConnectionUpdate(mClientIf, mDevice.getAddress(),
-                                               minConnectionInterval, maxConnectionInterval,
-                                               slaveLatency, supervisionTimeout);
+                                        minConnectionInterval, maxConnectionInterval,
+                                        slaveLatency, supervisionTimeout,
+                                        minConnectionEventLen, maxConnectionEventLen);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
             return false;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 08513aa..a34bd09 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -3000,6 +3000,21 @@
     }
 
     /**
+     * Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
+     *
+     * @param viewId The id of the view on which to call the method.
+     * @param methodName The name of the method to call.
+     * @param value The value to pass to the method.
+     *
+     * @hide
+     */
+    public void setColorStateList(int viewId, String methodName, ColorStateList value) {
+        addAction(new ReflectionAction(viewId, methodName, ReflectionAction.COLOR_STATE_LIST,
+                value));
+    }
+
+
+    /**
      * Call a method taking one long on a view in the layout for this RemoteViews.
      *
      * @param viewId The id of the view on which to call the method.
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 577fa17..0f13078 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -558,13 +558,6 @@
         }
     }
 
-    public static int resolveActionBarColor(Context context, int backgroundColor) {
-        if (backgroundColor == Notification.COLOR_DEFAULT) {
-            return context.getColor(com.android.internal.R.color.notification_action_list);
-        }
-        return getShiftedColor(backgroundColor, 7);
-    }
-
     /**
      * Get a color that stays in the same tint, but darkens or lightens it by a certain
      * amount.
diff --git a/core/java/com/android/internal/widget/EmphasizedNotificationButton.java b/core/java/com/android/internal/widget/EmphasizedNotificationButton.java
new file mode 100644
index 0000000..5213746
--- /dev/null
+++ b/core/java/com/android/internal/widget/EmphasizedNotificationButton.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.DrawableWrapper;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.InsetDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.util.AttributeSet;
+import android.view.RemotableViewMethod;
+import android.widget.Button;
+import android.widget.RemoteViews;
+
+/**
+ * A button implementation for the emphasized notification style.
+ *
+ * @hide
+ */
+@RemoteViews.RemoteView
+public class EmphasizedNotificationButton extends Button {
+    private final RippleDrawable mRipple;
+    private final int mStrokeWidth;
+    private final int mStrokeColor;
+
+    public EmphasizedNotificationButton(Context context) {
+        this(context, null);
+    }
+
+    public EmphasizedNotificationButton(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public EmphasizedNotificationButton(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public EmphasizedNotificationButton(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        DrawableWrapper background = (DrawableWrapper) getBackground().mutate();
+        mRipple = (RippleDrawable) background.getDrawable();
+        mStrokeWidth = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.emphasized_button_stroke_width);
+        mStrokeColor = getContext().getColor(com.android.internal.R.color.material_grey_300);
+        mRipple.mutate();
+    }
+
+    @RemotableViewMethod
+    public void setRippleColor(ColorStateList color) {
+        mRipple.setColor(color);
+        invalidate();
+    }
+
+    @RemotableViewMethod
+    public void setButtonBackground(ColorStateList color) {
+        GradientDrawable inner = (GradientDrawable) mRipple.getDrawable(0);
+        inner.setColor(color);
+        invalidate();
+    }
+
+    @RemotableViewMethod
+    public void setHasStroke(boolean hasStroke) {
+        GradientDrawable inner = (GradientDrawable) mRipple.getDrawable(0);
+        inner.setStroke(hasStroke ? mStrokeWidth : 0, mStrokeColor);
+        invalidate();
+    }
+}
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index e013553..5729b53 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -16,17 +16,15 @@
 
 package com.android.internal.widget;
 
-import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.view.Gravity;
 import android.view.RemotableViewMethod;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 import android.widget.TextView;
@@ -45,9 +43,11 @@
     private int mTotalWidth = 0;
     private ArrayList<Pair<Integer, TextView>> mMeasureOrderTextViews = new ArrayList<>();
     private ArrayList<View> mMeasureOrderOther = new ArrayList<>();
-    private boolean mMeasureLinearly;
-    private int mDefaultPaddingEnd;
-    private Drawable mDefaultBackground;
+    private boolean mEmphasizedMode;
+    private int mDefaultPaddingBottom;
+    private int mDefaultPaddingTop;
+    private int mEmphasizedHeight;
+    private int mRegularHeight;
 
     public NotificationActionListLayout(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -68,7 +68,7 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        if (mMeasureLinearly) {
+        if (mEmphasizedMode) {
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
             return;
         }
@@ -107,21 +107,23 @@
                 }
             }
         }
-        if (notGoneChildren > 1 && needRebuild) {
+        boolean centerAligned = (mGravity & Gravity.CENTER_HORIZONTAL) != 0;
+        boolean singleChildCentered = notGoneChildren == 1 && centerAligned;
+        boolean needsRegularMeasurement = notGoneChildren > 1 || singleChildCentered;
+
+        if (needsRegularMeasurement && needRebuild) {
             rebuildMeasureOrder(textViews, otherViews);
         }
 
         final boolean constrained =
                 MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED;
-        final boolean centerAligned = (mGravity & Gravity.CENTER_HORIZONTAL) != 0;
 
         final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
         final int otherSize = mMeasureOrderOther.size();
         int usedWidth = 0;
 
-        // Optimization: Don't do this if there's only one child.
         int measuredChildren = 0;
-        for (int i = 0; i < N && notGoneChildren > 1; i++) {
+        for (int i = 0; i < N && needsRegularMeasurement; i++) {
             // Measure shortest children first. To avoid measuring twice, we approximate by looking
             // at the text length.
             View c;
@@ -219,7 +221,7 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        if (mMeasureLinearly) {
+        if (mEmphasizedMode) {
             super.onLayout(changed, left, top, right, bottom);
             return;
         }
@@ -280,8 +282,21 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mDefaultPaddingEnd = getPaddingEnd();
-        mDefaultBackground = getBackground();
+        mDefaultPaddingBottom = getPaddingBottom();
+        mDefaultPaddingTop = getPaddingTop();
+        updateHeights();
+    }
+
+    private void updateHeights() {
+        int paddingTop = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin);
+        // same padding on bottom and at end
+        int paddingBottom = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_end);
+        mEmphasizedHeight = paddingBottom + paddingTop + getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_action_emphasized_height);
+        mRegularHeight = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_action_list_height);
     }
 
     /**
@@ -291,11 +306,38 @@
      */
     @RemotableViewMethod
     public void setEmphasizedMode(boolean emphasizedMode) {
-        mMeasureLinearly = emphasizedMode;
-        setPaddingRelative(getPaddingStart(), getPaddingTop(),
-                emphasizedMode ? 0 : mDefaultPaddingEnd, getPaddingBottom());
-        setBackground(emphasizedMode ? null : mDefaultBackground);
-        requestLayout();
+        mEmphasizedMode = emphasizedMode;
+        int height;
+        if (emphasizedMode) {
+            int paddingTop = getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.notification_content_margin);
+            // same padding on bottom and at end
+            int paddingBottom = getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.notification_content_margin_end);
+            height = mEmphasizedHeight;
+            int buttonPaddingInternal = getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.button_inset_vertical_material);
+            setPaddingRelative(getPaddingStart(),
+                    paddingTop - buttonPaddingInternal,
+                    getPaddingEnd(),
+                    paddingBottom - buttonPaddingInternal);
+        } else {
+            setPaddingRelative(getPaddingStart(),
+                    mDefaultPaddingTop,
+                    getPaddingEnd(),
+                    mDefaultPaddingBottom);
+            height = mRegularHeight;
+        }
+        ViewGroup.LayoutParams layoutParams = getLayoutParams();
+        layoutParams.height = height;
+        setLayoutParams(layoutParams);
+    }
+
+    public int getExtraMeasureHeight() {
+        if (mEmphasizedMode) {
+            return mEmphasizedHeight - mRegularHeight;
+        }
+        return 0;
     }
 
     public static final Comparator<Pair<Integer, TextView>> MEASURE_ORDER_COMPARATOR
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index c2fedf5..d75f135 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -20,11 +20,19 @@
 option java_multiple_files = true;
 option java_outer_classname = "GraphicsStatsServiceProto";
 
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+// This file is based on frameworks/base/libs/hwui/protos/graphicsstats.proto.
+// Please try to keep the two files in sync.
+
 message GraphicsStatsServiceDumpProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     repeated GraphicsStatsProto stats = 1;
 }
 
 message GraphicsStatsProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // The package name of the app
     optional string package_name = 1;
@@ -46,6 +54,8 @@
 }
 
 message GraphicsStatsJankSummaryProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Distinct frame count.
     optional int32 total_frames = 1;
 
@@ -73,6 +83,8 @@
 }
 
 message GraphicsStatsHistogramBucketProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Lower bound of render time in milliseconds.
     optional int32 render_millis = 1;
     // Number of frames in the bucket.
diff --git a/core/res/res/anim/flat_button_state_list_anim_material.xml b/core/res/res/anim/flat_button_state_list_anim_material.xml
new file mode 100644
index 0000000..266f14a
--- /dev/null
+++ b/core/res/res/anim/flat_button_state_list_anim_material.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 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
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:state_enabled="true">
+        <set>
+            <objectAnimator android:propertyName="translationZ"
+                            android:duration="@integer/button_pressed_animation_duration"
+                            android:valueTo="1dp"
+                            android:valueType="floatType"/>
+        </set>
+    </item>
+    <!-- base state -->
+    <item android:state_enabled="true">
+        <set>
+            <objectAnimator android:propertyName="translationZ"
+                            android:duration="@integer/button_pressed_animation_duration"
+                            android:valueTo="0"
+                            android:startDelay="@integer/button_pressed_animation_delay"
+                            android:valueType="floatType"/>
+        </set>
+    </item>
+    <item>
+        <set>
+            <objectAnimator android:propertyName="translationZ"
+                            android:duration="0"
+                            android:valueTo="0"
+                            android:valueType="floatType"/>
+        </set>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/btn_notification_emphasized.xml b/core/res/res/drawable/btn_notification_emphasized.xml
new file mode 100644
index 0000000..1a574fe
--- /dev/null
+++ b/core/res/res/drawable/btn_notification_emphasized.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 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
+  -->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:insetLeft="@dimen/button_inset_horizontal_material"
+       android:insetTop="@dimen/button_inset_vertical_material"
+       android:insetRight="@dimen/button_inset_horizontal_material"
+       android:insetBottom="@dimen/button_inset_vertical_material">
+    <ripple android:color="?attr/colorControlHighlight">
+        <item>
+            <shape android:shape="rectangle">
+                <corners android:radius="?attr/buttonCornerRadius" />
+                <padding android:left="@dimen/button_padding_horizontal_material"
+                         android:top="@dimen/button_padding_vertical_material"
+                         android:right="@dimen/button_padding_horizontal_material"
+                         android:bottom="@dimen/button_padding_vertical_material" />
+                <solid android:color="@color/white" />
+                <stroke android:width="@dimen/emphasized_button_stroke_width"
+                        android:color="@color/material_grey_300"/>
+            </shape>
+        </item>
+    </ripple>
+</inset>
diff --git a/core/res/res/layout/car_user_switching_dialog.xml b/core/res/res/layout/car_user_switching_dialog.xml
new file mode 100644
index 0000000..7ce35df
--- /dev/null
+++ b/core/res/res/layout/car_user_switching_dialog.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fitsSystemWindows="true"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+
+  <ImageView
+      android:id="@+id/user_loading_avatar"
+      android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
+      android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+      android:layout_centerHorizontal="true"
+  />
+
+  <TextView android:id="@+id/user_loading"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:layout_marginTop="@dimen/car_padding_4"
+      android:textSize="@dimen/car_body1_size"
+      android:textColor="@color/car_body1_light"
+      android:layout_below="@id/user_loading_avatar"
+      android:gravity="center"
+  />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/notification_material_action_emphasized.xml b/core/res/res/layout/notification_material_action_emphasized.xml
index 1e364cc..a6b7b38 100644
--- a/core/res/res/layout/notification_material_action_emphasized.xml
+++ b/core/res/res/layout/notification_material_action_emphasized.xml
@@ -14,21 +14,16 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/button_holder"
+<com.android.internal.widget.EmphasizedNotificationButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/NotificationEmphasizedAction"
+    android:id="@+id/action0"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:layout_marginStart="12dp"
     android:layout_weight="1"
-    android:background="#ff000000">
-    <Button
-        style="@android:style/Widget.Material.Light.Button.Borderless.Small"
-        android:id="@+id/action0"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:gravity="center"
-        android:textColor="@color/notification_default_color"
-        android:singleLine="true"
-        android:ellipsize="end"
-        android:background="@drawable/notification_material_action_background"
-        />
-</FrameLayout>
+    android:gravity="center"
+    android:textColor="@color/notification_default_color"
+    android:singleLine="true"
+    android:ellipsize="end"
+/>
diff --git a/core/res/res/layout/user_switching_dialog.xml b/core/res/res/layout/user_switching_dialog.xml
index 496783a..c806210 100644
--- a/core/res/res/layout/user_switching_dialog.xml
+++ b/core/res/res/layout/user_switching_dialog.xml
@@ -24,4 +24,4 @@
         android:paddingStart="?attr/dialogPreferredPadding"
         android:paddingEnd="?attr/dialogPreferredPadding"
         android:paddingTop="24dp"
-        android:paddingBottom="24dp" />
+        android:paddingBottom="24dp" />
\ No newline at end of file
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index c63f319..9215f3f 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -148,7 +148,6 @@
     <color name="notification_progress_background_color">@color/secondary_text_material_light</color>
 
     <color name="notification_action_list">#ffeeeeee</color>
-    <color name="notification_action_list_dark">#ffe0e0e0</color>
 
     <!-- Keyguard colors -->
     <color name="keyguard_avatar_frame_color">#ffffffff</color>
diff --git a/core/res/res/values/colors_car.xml b/core/res/res/values/colors_car.xml
new file mode 100644
index 0000000..6053728
--- /dev/null
+++ b/core/res/res/values/colors_car.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+  <!-- car support colors from
+  https://cs.corp.google.com/android/frameworks/support/car/res/values/colors.xml -->
+  <color name="car_user_switcher_user_image_bgcolor">@color/car_grey_50</color>
+  <color name="car_user_switcher_user_image_fgcolor">@color/car_grey_900</color>
+  <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
+  <color name="car_body1_light">@color/car_grey_100</color>
+
+  <color name="car_grey_50">#fffafafa</color>
+  <color name="car_grey_900">#ff212121</color>
+  <color name="car_dark_blue_grey_700">#ff172026</color>
+  <color name="car_grey_100">#fff5f5f5</color>
+</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 6e8134b..3609fb8 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -97,7 +97,7 @@
     <color name="material_deep_teal_100">#ffb2dfdb</color>
     <color name="material_deep_teal_200">#ff80cbc4</color>
     <color name="material_deep_teal_300">#ff4db6ac</color>
-    <color name="material_deep_teal_500">#ff009688</color>
+    <color name="material_deep_teal_500">#ff008577</color>
 
     <color name="material_blue_grey_200">#ffb0bec5</color>
     <color name="material_blue_grey_700">#ff455a64</color>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 0581856..2aa40fd 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -182,6 +182,12 @@
     <!-- The height of the notification action list -->
     <dimen name="notification_action_list_height">60dp</dimen>
 
+    <!-- The height of the notification action list -->
+    <dimen name="notification_action_emphasized_height">48dp</dimen>
+
+    <!-- Size of the stroke with for the emphasized notification button style -->
+    <dimen name="emphasized_button_stroke_width">1dp</dimen>
+
     <!-- height of the content margin to accomodate for the header -->
     <dimen name="notification_content_margin_top">46dp</dimen>
 
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
new file mode 100644
index 0000000..7d14f86
--- /dev/null
+++ b/core/res/res/values/dimens_car.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+    <!-- TODO replace with car support lib sizes when available -->
+    <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
+    <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
+    <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
+    <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
+    <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
+    <dimen name="car_padding_4">20dp</dimen>
+    <dimen name="car_body1_size">32sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 04f4d6e..3571967 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4957,4 +4957,8 @@
     <string name="notification_app_name_system">System</string>
     <!-- Application name displayed in notifications [CHAR LIMIT=60] -->
     <string name="notification_app_name_settings">Settings</string>
+
+    <!-- Strings for car -->
+    <!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
+    <string name="car_loading_profile">Loading</string>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e14aa14..984461b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1510,4 +1510,10 @@
         <item name="gravity">top</item>
     </style>
 
+    <!-- Colored bordered ink button -->
+    <style name="NotificationEmphasizedAction" parent="Widget.Material.Button">
+        <item name="background">@drawable/btn_notification_emphasized</item>
+        <item name="stateListAnimator">@anim/flat_button_state_list_anim_material</item>
+    </style>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b6f0b70..0de2cb0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2814,7 +2814,6 @@
 
   <java-symbol type="color" name="notification_action_list" />
   <java-symbol type="color" name="notification_material_background_color" />
-  <java-symbol type="color" name="notification_action_list_dark" />
 
   <!-- Resolver target actions -->
   <java-symbol type="array" name="resolver_target_actions_pin" />
@@ -2864,6 +2863,7 @@
   <java-symbol type="dimen" name="input_extract_action_button_height" />
 
   <java-symbol type="dimen" name="notification_action_list_height" />
+  <java-symbol type="dimen" name="notification_action_emphasized_height" />
 
   <!-- TV Remote Service package -->
   <java-symbol type="string" name="config_tvRemoteServicePackage" />
@@ -2889,8 +2889,6 @@
   <!-- Used internally for assistant to launch activity transitions -->
   <java-symbol type="id" name="cross_task_transition" />
 
-  <java-symbol type="id" name="button_holder" />
-
   <java-symbol type="bool" name="config_useRoundIcon" />
 
   <!-- For System navigation keys -->
@@ -3225,6 +3223,9 @@
   <java-symbol type="drawable" name="stat_sys_vitals" />
 
   <java-symbol type="color" name="text_color_primary" />
+  <java-symbol type="color" name="material_grey_300" />
+  <java-symbol type="dimen" name="emphasized_button_stroke_width" />
+  <java-symbol type="dimen" name="button_inset_vertical_material" />
 
   <java-symbol type="array" name="config_batteryPackageTypeSystem" />
   <java-symbol type="array" name="config_batteryPackageTypeService" />
@@ -3271,7 +3272,6 @@
   <java-symbol type="id" name="remote_input_progress" />
   <java-symbol type="id" name="remote_input_send" />
   <java-symbol type="id" name="remote_input" />
-  <java-symbol type="dimen" name="notification_content_margin" />
   <java-symbol type="dimen" name="slice_shortcut_size" />
   <java-symbol type="dimen" name="slice_icon_size" />
   <java-symbol type="dimen" name="slice_padding" />
@@ -3344,4 +3344,19 @@
 
   <java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
 
+  <!-- For car devices -->
+  <java-symbol type="string" name="car_loading_profile" />
+  <java-symbol type="color" name="car_body1_light" />
+  <java-symbol type="color" name="car_user_switcher_user_image_bgcolor" />
+  <java-symbol type="color" name="car_user_switcher_user_image_fgcolor" />
+  <java-symbol type="color" name="car_card_dark" />
+  <java-symbol type="dimen" name="car_body1_size" />
+  <java-symbol type="dimen" name="car_padding_4" />
+  <java-symbol type="dimen" name="car_fullscreen_user_pod_icon_text_size" />
+  <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_height" />
+  <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_width" />
+  <java-symbol type="layout" name="car_user_switching_dialog" />
+  <java-symbol type="id" name="user_loading_avatar" />
+  <java-symbol type="id" name="user_loading" />
+
 </resources>
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 592a6e6..213fa8e 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -69,7 +69,6 @@
         "libRScpp",
     ],
     static_libs: [
-        "libplatformprotos",
         "libEGL_blobCache",
     ],
 }
@@ -269,6 +268,7 @@
         "TextureCache.cpp",
         "VectorDrawable.cpp",
         "VkLayer.cpp",
+        "protos/graphicsstats.proto",
         "protos/hwui.proto",
     ],
 
diff --git a/libs/hwui/protos/graphicsstats.proto b/libs/hwui/protos/graphicsstats.proto
new file mode 100644
index 0000000..1226d44
--- /dev/null
+++ b/libs/hwui/protos/graphicsstats.proto
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto2";
+
+package android.uirenderer.protos;
+
+option optimize_for = LITE_RUNTIME;
+
+// frameworks/base/core/proto/android/service/graphicsstats.proto is based on
+// this proto. Please only make valid protobuf changes to these messages, and
+// keep the other file in sync with this one.
+
+message GraphicsStatsServiceDumpProto {
+    repeated GraphicsStatsProto stats = 1;
+}
+
+message GraphicsStatsProto {
+    // The package name of the app
+    optional string package_name = 1;
+
+    // The version code of the app
+    optional int64 version_code = 2;
+
+    // The start & end timestamps in UTC as
+    // milliseconds since January 1, 1970
+    // Compatible with java.util.Date#setTime()
+    optional int64 stats_start = 3;
+    optional int64 stats_end = 4;
+
+    // The aggregated statistics for the package
+    optional GraphicsStatsJankSummaryProto summary = 5;
+
+    // The frame time histogram for the package
+    repeated GraphicsStatsHistogramBucketProto histogram = 6;
+}
+
+message GraphicsStatsJankSummaryProto {
+    // Distinct frame count.
+    optional int32 total_frames = 1;
+
+    // Number of frames with slow render time. Frames are considered janky if
+    // they took more than a vsync interval (typically 16.667ms) to be rendered.
+    optional int32 janky_frames = 2;
+
+    // Number of "missed vsync" events.
+    optional int32 missed_vsync_count = 3;
+
+    // Number of frames in triple-buffering scenario (high input latency)
+    optional int32 high_input_latency_count = 4;
+
+    // Number of "slow UI thread" events.
+    optional int32 slow_ui_thread_count = 5;
+
+    // Number of "slow bitmap upload" events.
+    optional int32 slow_bitmap_upload_count = 6;
+
+    // Number of "slow draw" events.
+    optional int32 slow_draw_count = 7;
+
+    // Number of frames that missed their deadline (aka, visibly janked)
+    optional int32 missed_deadline_count = 8;
+}
+
+message GraphicsStatsHistogramBucketProto {
+    // Lower bound of render time in milliseconds.
+    optional int32 render_millis = 1;
+    // Number of frames in the bucket.
+    optional int32 frame_count = 2;
+}
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 599226b..7f8cb2d 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -17,8 +17,8 @@
 #include "GraphicsStatsService.h"
 
 #include "JankTracker.h"
+#include "protos/graphicsstats.pb.h"
 
-#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <log/log.h>
 
@@ -41,10 +41,10 @@
 
 constexpr int sHistogramSize = ProfileData::HistogramSize();
 
-static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
+static bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto,
                                       const std::string& package, int64_t versionCode,
                                       int64_t startTime, int64_t endTime, const ProfileData* data);
-static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
+static void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int outFd);
 
 class FileDescriptor {
 public:
@@ -104,7 +104,7 @@
 };
 
 bool GraphicsStatsService::parseFromFile(const std::string& path,
-                                         service::GraphicsStatsProto* output) {
+                                         protos::GraphicsStatsProto* output) {
     FileDescriptor fd{open(path.c_str(), O_RDONLY)};
     if (!fd.valid()) {
         int err = errno;
@@ -153,7 +153,7 @@
     return success;
 }
 
-bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
+bool mergeProfileDataIntoProto(protos::GraphicsStatsProto* proto, const std::string& package,
                                int64_t versionCode, int64_t startTime, int64_t endTime,
                                const ProfileData* data) {
     if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
@@ -193,7 +193,7 @@
     data->histogramForEach([&](ProfileData::HistogramEntry entry) {
         if (hitMergeError) return;
 
-        service::GraphicsStatsHistogramBucketProto* bucket;
+        protos::GraphicsStatsHistogramBucketProto* bucket;
         if (creatingHistogram) {
             bucket = proto->add_histogram();
             bucket->set_render_millis(entry.renderTimeMs);
@@ -212,7 +212,7 @@
     return !hitMergeError;
 }
 
-static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
+static int32_t findPercentile(protos::GraphicsStatsProto* proto, int percentile) {
     int32_t pos = percentile * proto->summary().total_frames() / 100;
     int32_t remaining = proto->summary().total_frames() - pos;
     for (auto it = proto->histogram().rbegin(); it != proto->histogram().rend(); ++it) {
@@ -224,7 +224,7 @@
     return 0;
 }
 
-void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
+void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int fd) {
     // This isn't a full validation, just enough that we can deref at will
     if (proto->package_name().empty() || !proto->has_summary()) {
         ALOGW("Skipping dump, invalid package_name() '%s' or summary %d",
@@ -259,7 +259,7 @@
 void GraphicsStatsService::saveBuffer(const std::string& path, const std::string& package,
                                       int64_t versionCode, int64_t startTime, int64_t endTime,
                                       const ProfileData* data) {
-    service::GraphicsStatsProto statsProto;
+    protos::GraphicsStatsProto statsProto;
     if (!parseFromFile(path, &statsProto)) {
         statsProto.Clear();
     }
@@ -310,12 +310,12 @@
     Dump(int outFd, DumpType type) : mFd(outFd), mType(type) {}
     int fd() { return mFd; }
     DumpType type() { return mType; }
-    service::GraphicsStatsServiceDumpProto& proto() { return mProto; }
+    protos::GraphicsStatsServiceDumpProto& proto() { return mProto; }
 
 private:
     int mFd;
     DumpType mType;
-    service::GraphicsStatsServiceDumpProto mProto;
+    protos::GraphicsStatsServiceDumpProto mProto;
 };
 
 GraphicsStatsService::Dump* GraphicsStatsService::createDump(int outFd, DumpType type) {
@@ -325,7 +325,7 @@
 void GraphicsStatsService::addToDump(Dump* dump, const std::string& path,
                                      const std::string& package, int64_t versionCode,
                                      int64_t startTime, int64_t endTime, const ProfileData* data) {
-    service::GraphicsStatsProto statsProto;
+    protos::GraphicsStatsProto statsProto;
     if (!path.empty() && !parseFromFile(path, &statsProto)) {
         statsProto.Clear();
     }
@@ -347,7 +347,7 @@
 }
 
 void GraphicsStatsService::addToDump(Dump* dump, const std::string& path) {
-    service::GraphicsStatsProto statsProto;
+    protos::GraphicsStatsProto statsProto;
     if (!parseFromFile(path, &statsProto)) {
         return;
     }
diff --git a/libs/hwui/service/GraphicsStatsService.h b/libs/hwui/service/GraphicsStatsService.h
index bce0f3d..389f599 100644
--- a/libs/hwui/service/GraphicsStatsService.h
+++ b/libs/hwui/service/GraphicsStatsService.h
@@ -22,12 +22,11 @@
 #include "utils/Macros.h"
 
 namespace android {
-namespace service {
+namespace uirenderer {
+namespace protos {
 class GraphicsStatsProto;
 }
 
-namespace uirenderer {
-
 /*
  * The exported entry points used by GraphicsStatsService.java in f/b/services/core
  *
@@ -55,8 +54,8 @@
     ANDROID_API static void finishDump(Dump* dump);
 
     // Visible for testing
-    static bool parseFromFile(const std::string& path, service::GraphicsStatsProto* output);
+    static bool parseFromFile(const std::string& path, protos::GraphicsStatsProto* output);
 };
 
 } /* namespace uirenderer */
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
index 30c3b4e..098b4cc 100644
--- a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
+++ b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
@@ -16,10 +16,9 @@
 
 #include <gtest/gtest.h>
 
+#include "protos/graphicsstats.pb.h"
 #include "service/GraphicsStatsService.h"
 
-#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -74,7 +73,7 @@
         mockData.editSlowFrameCounts()[i] = (i % 5) + 1;
     }
     GraphicsStatsService::saveBuffer(path, packageName, 5, 3000, 7000, &mockData);
-    service::GraphicsStatsProto loadedProto;
+    protos::GraphicsStatsProto loadedProto;
     EXPECT_TRUE(GraphicsStatsService::parseFromFile(path, &loadedProto));
     // Clean up the file
     unlink(path.c_str());
@@ -130,7 +129,7 @@
     }
     GraphicsStatsService::saveBuffer(path, packageName, 5, 7050, 10000, &mockData);
 
-    service::GraphicsStatsProto loadedProto;
+    protos::GraphicsStatsProto loadedProto;
     EXPECT_TRUE(GraphicsStatsService::parseFromFile(path, &loadedProto));
     // Clean up the file
     unlink(path.c_str());
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 4857a87..7ac0d96 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -34,7 +34,7 @@
     LightBlue_300 = 0xFF4FC3F7,
     LightBlue_500 = 0xFF03A9F4,
     Cyan_500 = 0xFF00BCD4,
-    Teal_500 = 0xFF009688,
+    Teal_500 = 0xFF008577,
     Teal_700 = 0xFF00796B,
     Green_500 = 0xFF4CAF50,
     Green_700 = 0xFF388E3C,
diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
index 6f82f68..a7eb30d 100644
--- a/media/java/android/media/update/ApiLoader.java
+++ b/media/java/android/media/update/ApiLoader.java
@@ -16,68 +16,14 @@
 
 package android.media.update;
 
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.UserHandle;
-
-import com.android.internal.annotations.GuardedBy;
-
-import dalvik.system.PathClassLoader;
-
-import java.io.File;
-
 /**
  * @hide
  */
 public final class ApiLoader {
-    @GuardedBy("this")
-    private static StaticProvider sMediaUpdatable;
-
-    private static final String UPDATE_PACKAGE = "com.android.media.update";
-    private static final String UPDATE_CLASS = "com.android.media.update.ApiFactory";
-    private static final String UPDATE_METHOD = "initialize";
-    private static final boolean REGISTER_UPDATE_DEPENDENCY = true;
-
     private ApiLoader() { }
 
     public static StaticProvider getProvider() {
-        if (sMediaUpdatable != null) return sMediaUpdatable;
-
-        try {
-            return getMediaUpdatable();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } catch (NameNotFoundException | ReflectiveOperationException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    // TODO This method may do I/O; Ensure it does not violate (emit warnings in) strict mode.
-    private static synchronized StaticProvider getMediaUpdatable()
-            throws NameNotFoundException, ReflectiveOperationException, RemoteException {
-        if (sMediaUpdatable != null) return sMediaUpdatable;
-
-        // TODO Figure out when to use which package (query media update service)
-        int flags = Build.IS_DEBUGGABLE ? 0 : PackageManager.MATCH_FACTORY_ONLY;
-        flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
-        ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
-                UPDATE_PACKAGE, flags, UserHandle.myUserId());
-
-        if (REGISTER_UPDATE_DEPENDENCY) {
-            // Register a dependency to the updatable in order to be killed during updates
-            ActivityManager.getService().addPackageDependency(ai.packageName);
-        }
-
-        ClassLoader classLoader = new PathClassLoader(ai.sourceDir,
-                ai.nativeLibraryDir + File.pathSeparator + System.getProperty("java.library.path"),
-                ClassLoader.getSystemClassLoader().getParent());
-        return sMediaUpdatable = (StaticProvider) classLoader.loadClass(UPDATE_CLASS)
-                .getMethod(UPDATE_METHOD, ApplicationInfo.class).invoke(null, ai);
+        throw new RuntimeException("Use MediaSession/Browser instead of"
+                + " hidden MediaSession2/Browser2 APIs.");
     }
 }
diff --git a/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml b/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml
index 8196650..b8a0689 100644
--- a/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml
+++ b/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml
@@ -18,7 +18,7 @@
     android:height="36dp"
     android:viewportWidth="48.0"
     android:viewportHeight="48.0"
-    android:tint="@color/pdf_printer_color">
+    android:tint="@*android:color/accent_device_default_light">
     <path
         android:pathData="M40,4L16,4c-2.21,0 -4,1.79 -4,4v24c0,2.21 1.79,4 4,4h24c2.21,0 4,-1.79 4,-4L44,8c0,-2.21 -1.79,-4 -4,-4zM23,19c0,1.66 -1.34,3 -3,3h-2v4h-3L15,14h5c1.66,0 3,1.34 3,3v2zM33,23c0,1.66 -1.34,3 -3,3h-5L25,14h5c1.66,0 3,1.34 3,3v6zM41,17h-3v2h3v3h-3v4h-3L35,14h6v3zM18,19h2v-2h-2v2zM8,12L4,12v28c0,2.21 1.79,4 4,4h28v-4L8,40L8,12zM28,23h2v-6h-2v6z"
         android:fillColor="@android:color/black"/>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index a15fff5..68bc6f2 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -23,6 +23,4 @@
     <color name="unselected_page_background_color">#C0C0C0</color>
 
     <color name="material_grey_500">#ffa3a3a3</color>
-
-    <color name="pdf_printer_color">#009688</color>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 6413aab..1e0cce9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.ParcelUuid;
+import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import com.android.internal.R;
 import java.util.ArrayList;
@@ -41,6 +42,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+
 /**
  * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
  * objects for the available Bluetooth profiles.
@@ -130,7 +132,7 @@
         addProfile(mHidProfile, HidProfile.NAME,
                 BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
 
-        mPanProfile = new PanProfile(context);
+        mPanProfile = new PanProfile(context, mLocalAdapter);
         addPanProfile(mPanProfile, PanProfile.NAME,
                 BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
 
@@ -486,6 +488,16 @@
         return mHearingAidProfile;
     }
 
+    @VisibleForTesting
+    HidProfile getHidProfile() {
+        return mHidProfile;
+    }
+
+    @VisibleForTesting
+    HidDeviceProfile getHidDeviceProfile() {
+        return mHidDeviceProfile;
+    }
+
     /**
      * Fill in a list of LocalBluetoothProfile objects that are supported by
      * the local device and the remote device.
@@ -553,7 +565,7 @@
             removedProfiles.remove(mHidProfile);
         }
 
-        if (mHidProfile != null && mHidDeviceProfile.getConnectionStatus(device)
+        if (mHidDeviceProfile != null && mHidDeviceProfile.getConnectionStatus(device)
                 != BluetoothProfile.STATE_DISCONNECTED) {
             profiles.add(mHidDeviceProfile);
             removedProfiles.remove(mHidDeviceProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
index 3299cb2..e077a67 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
@@ -38,6 +38,7 @@
 
     private BluetoothPan mService;
     private boolean mIsProfileReady;
+    private final LocalBluetoothAdapter mLocalAdapter;
 
     // Tethering direction for each device
     private final HashMap<BluetoothDevice, Integer> mDeviceRoleMap =
@@ -68,10 +69,10 @@
         return mIsProfileReady;
     }
 
-    PanProfile(Context context) {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        adapter.getProfileProxy(context, new PanServiceListener(),
-                BluetoothProfile.PAN);
+    PanProfile(Context context, LocalBluetoothAdapter adapter) {
+        mLocalAdapter = adapter;
+        mLocalAdapter.getProfileProxy(context, new PanServiceListener(),
+            BluetoothProfile.PAN);
     }
 
     public boolean isConnectable() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
new file mode 100644
index 0000000..88c7a55
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(resourceDir = "../../res")
+public class LocalBluetoothProfileManagerTest {
+    @Mock private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock private BluetoothEventManager mEventManager;
+    @Mock private LocalBluetoothAdapter mAdapter;
+    @Mock private BluetoothDevice mDevice;
+    private Context mContext;
+    private LocalBluetoothProfileManager mProfileManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+    }
+
+    /**
+     * Verify HID and HID Device profiles are not null without running updateUuids()
+     */
+    @Test
+    public void constructor_initiateHidAndHidDeviceProfile() {
+        mProfileManager =
+                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+
+        assertThat(mProfileManager.getHidProfile()).isNotNull();
+        assertThat(mProfileManager.getHidDeviceProfile()).isNotNull();
+    }
+
+    /**
+     * Verify updateLocalProfiles() for a local A2DP source adds A2dpProfile
+     */
+    @Test
+    public void updateLocalProfiles_addA2dpToLocalProfiles() {
+        mProfileManager =
+                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[] {BluetoothUuid.AudioSource});
+        assertThat(mProfileManager.getA2dpProfile()).isNull();
+        assertThat(mProfileManager.getHeadsetProfile()).isNull();
+
+        ParcelUuid[] uuids = mAdapter.getUuids();
+        mProfileManager.updateLocalProfiles(uuids);
+
+        assertThat(mProfileManager.getA2dpProfile()).isNotNull();
+        assertThat(mProfileManager.getHeadsetProfile()).isNull();
+    }
+
+    /**
+     * Verify updateProfiles() for a remote HID device updates profiles and removedProfiles
+     */
+    @Test
+    public void updateProfiles_addHidProfileForRemoteDevice() {
+        mProfileManager =
+                new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+        ParcelUuid[] uuids = new ParcelUuid[]{BluetoothUuid.Hid};
+        ParcelUuid[] localUuids = new ParcelUuid[]{};
+        List<LocalBluetoothProfile> profiles = new ArrayList<>();
+        List<LocalBluetoothProfile> removedProfiles = new ArrayList<>();
+
+        mProfileManager.updateProfiles(uuids, localUuids, profiles, removedProfiles, false,
+                mDevice);
+
+        assertThat(mProfileManager.getHidProfile()).isNotNull();
+        assertThat(profiles.contains(mProfileManager.getHidProfile())).isTrue();
+        assertThat(removedProfiles.contains(mProfileManager.getHidProfile())).isFalse();
+    }
+}
diff --git a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
index 88fb2d2..71376d5 100644
--- a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
@@ -15,8 +15,8 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32dp"
-        android:height="32dp"
+        android:width="24dp"
+        android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
         android:tint="?android:attr/colorControlNormal">
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 67f68d3..c59b067 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -37,7 +37,7 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="@dimen/car_padding_4"
         android:textSize="@dimen/car_body1_size"
-        android:textColor="@color/qs_user_detail_name"
+        android:textColor="@color/car_body1_light"
         android:ellipsize="end"
         android:singleLine="true"
         android:gravity="center"
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 22452b7..27d0e46 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -18,20 +18,12 @@
         android:fitsSystemWindows="true"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@android:color/black"
+        android:background="@color/car_card_dark"
         android:visibility="gone">
 
-    <!-- This progressbar is activated while we're switching users. -->
-    <ProgressBar
-        android:id="@+id/switching_users"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:indeterminate="true"
-        android:visibility="gone"
-        android:layout_gravity="center" />
-
     <RelativeLayout
         android:id="@+id/container"
+        android:background="@color/car_card_dark"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
diff --git a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
index d607c8c..c8a5544 100644
--- a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
@@ -23,6 +23,7 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_vertical"
+    android:paddingStart="2dp"
     android:orientation="horizontal">
     <FrameLayout
         android:id="@+id/inout_container"
diff --git a/packages/SystemUI/res/layout/status_bar_wifi_group.xml b/packages/SystemUI/res/layout/status_bar_wifi_group.xml
index 08cef55..482f780 100644
--- a/packages/SystemUI/res/layout/status_bar_wifi_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_wifi_group.xml
@@ -22,61 +22,67 @@
     android:id="@+id/wifi_combo"
     android:layout_width="wrap_content"
     android:layout_height="match_parent"
-    android:paddingStart="4dp"
-    android:gravity="center_vertical"
-    android:orientation="horizontal" >
+    android:gravity="center_vertical" >
 
-    <FrameLayout
-            android:id="@+id/inout_container"
-            android:layout_height="17dp"
+    <com.android.keyguard.AlphaOptimizedLinearLayout
+        android:id="@+id/wifi_group"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:paddingStart="2dp"
+        android:gravity="center_vertical"
+    >
+        <FrameLayout
+                android:id="@+id/inout_container"
+                android:layout_height="17dp"
+                android:layout_width="wrap_content"
+                android:gravity="center_vertical" >
+            <ImageView
+                android:id="@+id/wifi_in"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:src="@drawable/ic_activity_down"
+                android:visibility="gone"
+                android:paddingEnd="2dp"
+            />
+            <ImageView
+                android:id="@+id/wifi_out"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:src="@drawable/ic_activity_up"
+                android:paddingEnd="2dp"
+                android:visibility="gone"
+            />
+        </FrameLayout>
+        <FrameLayout
+            android:id="@+id/wifi_combo"
+            android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:gravity="center_vertical" >
-        <ImageView
-            android:id="@+id/wifi_in"
-            android:layout_height="wrap_content"
+            <com.android.systemui.statusbar.AlphaOptimizedImageView
+                android:theme="?attr/lightIconTheme"
+                android:id="@+id/wifi_signal"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content" />
+        </FrameLayout>
+
+        <View
+            android:id="@+id/wifi_signal_spacer"
+            android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
+            android:layout_height="4dp"
+            android:visibility="gone" />
+
+        <!-- Looks like CarStatusBar uses this... -->
+        <ViewStub
+            android:id="@+id/connected_device_signals_stub"
+            android:layout="@layout/connected_device_signal"
             android:layout_width="wrap_content"
-            android:src="@drawable/ic_activity_down"
-            android:visibility="gone"
-            android:paddingEnd="2dp"
-        />
-        <ImageView
-            android:id="@+id/wifi_out"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:src="@drawable/ic_activity_up"
-            android:paddingEnd="2dp"
+            android:layout_height="wrap_content" />
+
+        <View
+            android:id="@+id/wifi_airplane_spacer"
+            android:layout_width="@dimen/status_bar_airplane_spacer_width"
+            android:layout_height="4dp"
             android:visibility="gone"
         />
-    </FrameLayout>
-    <FrameLayout
-        android:id="@+id/wifi_combo"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:gravity="center_vertical" >
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:theme="?attr/lightIconTheme"
-            android:id="@+id/wifi_signal"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content" />
-    </FrameLayout>
-
-    <View
-        android:id="@+id/wifi_signal_spacer"
-        android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
-        android:layout_height="4dp"
-        android:visibility="gone" />
-
-    <!-- Looks like CarStatusBar uses this... -->
-    <ViewStub
-        android:id="@+id/connected_device_signals_stub"
-        android:layout="@layout/connected_device_signal"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-
-    <View
-        android:id="@+id/wifi_airplane_spacer"
-        android:layout_width="@dimen/status_bar_airplane_spacer_width"
-        android:layout_height="4dp"
-        android:visibility="gone"
-    />
+    </com.android.keyguard.AlphaOptimizedLinearLayout>
 </com.android.systemui.statusbar.StatusBarWifiView>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index d4fe1c6..dc4e255 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -17,11 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:padding="@dimen/volume_dialog_panel_transparent_padding"
     android:background="@android:color/transparent"
-    android:theme="@style/qs_theme"
-    android:clipChildren="false"
-    android:clipToPadding="false">
+    android:theme="@style/qs_theme">
     <!-- right-aligned to be physically near volume button -->
     <LinearLayout
         android:id="@+id/volume_dialog"
@@ -30,9 +27,11 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical|right"
         android:background="@android:color/transparent"
-        android:layout_margin="@dimen/volume_dialog_base_margin"
+        android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right"
+        android:paddingTop="@dimen/volume_dialog_panel_transparent_padding"
+        android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding"
+        android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding"
         android:orientation="vertical"
-        android:clipChildren="false"
         android:clipToPadding="false" >
 
         <FrameLayout
@@ -42,7 +41,6 @@
             android:layout_marginBottom="@dimen/volume_dialog_spacer"
             android:translationZ="@dimen/volume_dialog_elevation"
             android:layout_gravity="right"
-            android:clipChildren="false"
             android:clipToPadding="false"
             android:background="@drawable/rounded_bg_full">
             <com.android.keyguard.AlphaOptimizedImageButton
@@ -65,7 +63,6 @@
             android:layout_height="wrap_content"
             android:orientation="vertical"
             android:translationZ="@dimen/volume_dialog_elevation"
-            android:clipChildren="false"
             android:clipToPadding="false"
             android:background="@drawable/rounded_bg_full" >
             <LinearLayout
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b99e35b..e6694e9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -277,7 +277,9 @@
     <!-- The width of the panel that holds the quick settings. -->
     <dimen name="qs_panel_width">@dimen/notification_panel_width</dimen>
 
-    <dimen name="volume_dialog_panel_transparent_padding">8dp</dimen>
+    <dimen name="volume_dialog_panel_transparent_padding_right">8dp</dimen>
+
+    <dimen name="volume_dialog_panel_transparent_padding">20dp</dimen>
 
     <!-- the amount the volume panel should be offset at the end from the view next to it (or
     the screen edge, in portrait-->
@@ -944,7 +946,7 @@
     <!-- Fingerprint Dialog values -->
     <dimen name="fingerprint_dialog_fp_icon_size">64dp</dimen>
     <dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen>
-    <dimen name="fingerprint_dialog_corner_size">2dp</dimen>
+    <dimen name="fingerprint_dialog_corner_size">4dp</dimen>
 
     <!-- Wireless Charging Animation values -->
     <dimen name="wireless_charging_dots_radius_start">0dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 2b91891..0cd3825 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -20,7 +20,7 @@
     <dimen name="car_margin_standard">112dp</dimen>
 
     <!-- TODO replace with car support lib sizes when available -->
-    <dimen name="car_fullscreen_user_pod_icon_text_size">32sp</dimen>
+    <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
     <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
     <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
     <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 29f1335..a4ea5e8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -844,6 +844,10 @@
     <string name="recents_stack_action_button_label">Clear all</string>
     <!-- Recents: Hint text that shows on the drop targets to start multiwindow. [CHAR LIMIT=NONE] -->
     <string name="recents_drag_hint_message">Drag here to use split screen</string>
+    <!-- Recents: Text that shows above the navigation bar after launching a few apps. [CHAR LIMIT=NONE] -->
+    <string name="recents_swipe_up_onboarding">Swipe up to switch apps</string>
+    <!-- Recents: Text that shows above the navigation bar after launching several apps. [CHAR LIMIT=NONE] -->
+    <string name="recents_quick_scrub_onboarding">Drag right to quickly switch apps</string>
 
     <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
     <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 4799f39..f13be73 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -36,11 +36,6 @@
     void startScreenPinning(int taskId) = 1;
 
     /**
-     * Specifies the text to be shown for onboarding the new swipe-up gesture to access recents.
-     */
-    void setRecentsOnboardingText(CharSequence text) = 3;
-
-    /**
      * Enables/disables launcher/overview interaction features {@link InteractionType}.
      */
     void setInteractionState(int flags) = 4;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 0f52209..2bdbf0b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,8 +16,7 @@
 
 package com.android.systemui.shared.system;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-
+import android.app.WindowConfiguration;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.view.RemoteAnimationTarget;
@@ -29,9 +28,16 @@
 
     public static final int MODE_OPENING = RemoteAnimationTarget.MODE_OPENING;
     public static final int MODE_CLOSING = RemoteAnimationTarget.MODE_CLOSING;
+    public final int mode;
+
+    public static final int ACTIVITY_TYPE_UNDEFINED = WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+    public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+    public static final int ACTIVITY_TYPE_HOME = WindowConfiguration.ACTIVITY_TYPE_HOME;
+    public static final int ACTIVITY_TYPE_RECENTS = WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+    public static final int ACTIVITY_TYPE_ASSISTANT = WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+    public final int activityType;
 
     public final int taskId;
-    public final int mode;
     public final SurfaceControlCompat leash;
     public final boolean isTranslucent;
     public final Rect clipRect;
@@ -39,11 +45,9 @@
     public final Point position;
     public final Rect sourceContainerBounds;
     public final boolean isNotInRecents;
-
-    private final RemoteAnimationTarget mTarget;
+    public final Rect contentInsets;
 
     public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
-        mTarget = app;
         taskId = app.taskId;
         mode = app.mode;
         leash = new SurfaceControlCompat(app.leash);
@@ -53,6 +57,8 @@
         sourceContainerBounds = app.sourceContainerBounds;
         prefixOrderIndex = app.prefixOrderIndex;
         isNotInRecents = app.isNotInRecents;
+        contentInsets = app.contentInsets;
+        activityType = app.windowConfiguration.getActivityType();
     }
 
     public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
@@ -63,18 +69,4 @@
         }
         return appsCompat;
     }
-
-    /**
-     * TODO: Get as a method for compatibility (will move into ctor once Launcher updates)
-     */
-    public Rect getContentInsets() {
-        return mTarget.contentInsets;
-    }
-
-    /**
-     * TODO: Get as a method for compatibility (will move into ctor once Launcher updates)
-     */
-    public boolean isAssistantActivityType() {
-        return mTarget.windowConfiguration.getActivityType() == ACTIVITY_TYPE_ASSISTANT;
-    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index b1020cf..3443334 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -78,7 +78,6 @@
 
     private IOverviewProxy mOverviewProxy;
     private int mConnectionBackoffAttempts;
-    private CharSequence mOnboardingText;
     private @InteractionType int mInteractionFlags;
     private boolean mIsEnabled;
 
@@ -119,10 +118,6 @@
             }
         }
 
-        public void setRecentsOnboardingText(CharSequence text) {
-            mOnboardingText = text;
-        }
-
         public void setInteractionState(@InteractionType int flags) {
             long token = Binder.clearCallingIdentity();
             try {
@@ -286,10 +281,6 @@
         return mOverviewProxy;
     }
 
-    public CharSequence getOnboardingText() {
-        return mOnboardingText;
-    }
-
     public int getInteractionFlags() {
         return mInteractionFlags;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 216fa78..70880d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
 import com.android.systemui.statusbar.policy.Clock;
+import com.android.systemui.statusbar.phone.StatusIconContainer;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.statusbar.policy.DateView;
@@ -147,7 +148,9 @@
         mDate.setOnClickListener(this);
         mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
         mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
-        mIconManager = new TintedIconManager(findViewById(R.id.statusIcons));
+        StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
+        iconContainer.setShouldRestrictIcons(false);
+        mIconManager = new TintedIconManager(iconContainer);
 
         // Views corresponding to the header info section (e.g. tooltip and next alarm).
         mHeaderTextContainerView = findViewById(R.id.header_text_container);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 9883da6..c8c2158 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
+import android.os.SystemProperties;
 import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -29,7 +30,11 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSHost;
@@ -61,8 +66,15 @@
 
     @Override
     public void handleClick() {
-        MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
-        setEnabled(!mState.value);
+        boolean airplaneModeEnabled = mState.value;
+        MetricsLogger.action(mContext, getMetricsCategory(), !airplaneModeEnabled);
+        if (!airplaneModeEnabled && Boolean.parseBoolean(
+                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
+            Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(
+                    new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS), 0);
+            return;
+        }
+        setEnabled(!airplaneModeEnabled);
     }
 
     private void setEnabled(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 0d8aed4..901c7ae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -227,12 +227,7 @@
         if (!shouldShow()) {
             return;
         }
-        CharSequence onboardingText = mOverviewProxyService.getOnboardingText();
-        if (TextUtils.isEmpty(onboardingText)) {
-            Log.w(TAG, "Unable to get onboarding text");
-            return;
-        }
-        mTextView.setText(onboardingText);
+        mTextView.setText(R.string.recents_swipe_up_onboarding);
         // Only show in portrait.
         int orientation = mContext.getResources().getConfiguration().orientation;
         if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 8030bde..e527be1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -239,7 +239,9 @@
             }
         }
         if (mHeadsUpChild != null) {
-            int size = Math.min(maxSize, mHeadsUpHeight);
+            int maxHeight = mHeadsUpHeight;
+            maxHeight += mHeadsUpWrapper.getExtraMeasureHeight();
+            int size = Math.min(maxSize, maxHeight);
             ViewGroup.LayoutParams layoutParams = mHeadsUpChild.getLayoutParams();
             boolean useExactly = false;
             if (layoutParams.height >= 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index bd6bd12..4fc18ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -163,7 +163,6 @@
         mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
         mNumberPain.setAntiAlias(true);
         setNotification(sbn);
-        maybeUpdateIconScaleDimens();
         setScaleType(ScaleType.CENTER);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         if (mNotification != null) {
@@ -171,26 +170,18 @@
                     com.android.internal.R.color.notification_default_color_light));
         }
         reloadDimens();
+        maybeUpdateIconScaleDimens();
     }
 
+    /** Should always be preceded by {@link #reloadDimens()} */
     private void maybeUpdateIconScaleDimens() {
         // We do not resize and scale system icons (on the right), only notification icons (on the
         // left).
         if (mNotification != null || mAlwaysScaleIcon) {
-            updateIconScaleDimens();
+            updateIconScale();
         }
     }
 
-    private void updateIconScaleDimens() {
-        Resources res = mContext.getResources();
-        mStatusBarIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
-        mStatusBarIconDrawingSizeDark =
-                res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
-        mStatusBarIconDrawingSize =
-                res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
-        updateIconScale();
-    }
-
     private void updateIconScale() {
         final float imageBounds = NotificationUtils.interpolate(
                 mStatusBarIconDrawingSize,
@@ -214,15 +205,21 @@
         int density = newConfig.densityDpi;
         if (density != mDensity) {
             mDensity = density;
+            reloadDimens();
             maybeUpdateIconScaleDimens();
             updateDrawable();
-            reloadDimens();
         }
     }
 
     private void reloadDimens() {
         boolean applyRadius = mDotRadius == mStaticDotRadius;
-        mStaticDotRadius = getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius);
+        Resources res = getResources();
+        mStaticDotRadius = res.getDimensionPixelSize(R.dimen.overflow_dot_radius);
+        mStatusBarIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+        mStatusBarIconDrawingSizeDark =
+                res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
+        mStatusBarIconDrawingSize =
+                res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
         if (applyRadius) {
             mDotRadius = mStaticDotRadius;
         }
@@ -240,7 +237,8 @@
         mDozer = new NotificationIconDozeHelper(context);
         mBlocked = false;
         mAlwaysScaleIcon = true;
-        updateIconScaleDimens();
+        reloadDimens();
+        updateIconScale();
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
     }
 
@@ -425,7 +423,7 @@
                 radius = NotificationUtils.interpolate(mDotRadius, getWidth() / 4, fadeOutAmount);
             }
             mDotPaint.setAlpha((int) (alpha * 255));
-            canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mDotPaint);
+            canvas.drawCircle(mStatusBarIconSize / 2, getHeight() / 2, radius, mDotPaint);
         }
     }
 
@@ -657,6 +655,7 @@
         mContrastedDrawableColor = contrastedColor;
     }
 
+    @Override
     public void setVisibleState(int state) {
         setVisibleState(state, true /* animate */, null /* endRunnable */);
     }
@@ -872,7 +871,10 @@
 
     @Override
     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
-        setImageTintList(ColorStateList.valueOf(getTint(area, this, tint)));
+        int areaTint = getTint(area, this, tint);
+        ColorStateList color = ColorStateList.valueOf(areaTint);
+        setImageTintList(color);
+        setDecorColor(areaTint);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 51b4239..f4e45812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -197,10 +197,20 @@
     }
 
     @Override
+    public void setDecorColor(int color) {
+        //TODO: May also not be needed
+    }
+
+    @Override
     public boolean isIconVisible() {
         return mState.visible;
     }
 
+    @Override
+    public void setVisibleState(int state) {
+        //TODO: May not be needed. Mobile is always expected to be visible (not a dot)
+    }
+
     @VisibleForTesting
     public MobileIconState getState() {
         return mState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index 62cd16f..0e2714d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.statusbar;
 
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
 import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
 import static com.android.systemui.statusbar.policy.DarkIconDispatcher.isInArea;
 
@@ -24,11 +27,17 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.ContextThemeWrapper;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import android.widget.LinearLayout;
 import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
@@ -38,10 +47,14 @@
 /**
  * Start small: StatusBarWifiView will be able to layout from a WifiIconState
  */
-public class StatusBarWifiView extends AlphaOptimizedLinearLayout implements DarkReceiver,
+public class StatusBarWifiView extends FrameLayout implements DarkReceiver,
         StatusIconDisplayable {
     private static final String TAG = "StatusBarWifiView";
 
+    /// Used to show etc dots
+    private StatusBarIconView mDotView;
+    /// Contains the main icon layout
+    private LinearLayout mWifiGroup;
     private ImageView mWifiIcon;
     private ImageView mIn;
     private ImageView mOut;
@@ -55,9 +68,12 @@
     private ContextThemeWrapper mDarkContext;
     private ContextThemeWrapper mLightContext;
 
-    public static StatusBarWifiView fromContext(Context context) {
+    public static StatusBarWifiView fromContext(Context context, String slot) {
         LayoutInflater inflater = LayoutInflater.from(context);
-        return (StatusBarWifiView) inflater.inflate(R.layout.status_bar_wifi_group, null);
+        StatusBarWifiView v = (StatusBarWifiView) inflater.inflate(R.layout.status_bar_wifi_group, null);
+        v.setSlot(slot);
+        v.init();
+        return v;
     }
 
     public StatusBarWifiView(Context context) {
@@ -77,12 +93,6 @@
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        init();
-    }
-
     public void setSlot(String slot) {
         mSlot = slot;
     }
@@ -93,6 +103,12 @@
         mWifiIcon.setImageTintList(list);
         mIn.setImageTintList(list);
         mOut.setImageTintList(list);
+        mDotView.setDecorColor(color);
+    }
+
+    @Override
+    public void setDecorColor(int color) {
+        mDotView.setDecorColor(color);
     }
 
     @Override
@@ -105,18 +121,55 @@
         return mState != null && mState.visible;
     }
 
+    @Override
+    public void setVisibleState(int state) {
+        switch (state) {
+            case STATE_ICON:
+                mWifiGroup.setVisibility(View.VISIBLE);
+                mDotView.setVisibility(View.GONE);
+                break;
+            case STATE_DOT:
+                mWifiGroup.setVisibility(View.GONE);
+                mDotView.setVisibility(View.VISIBLE);
+                break;
+            case STATE_HIDDEN:
+            default:
+                setVisibility(View.GONE);
+                break;
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+    }
+
     private void init() {
         int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
         int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
         mLightContext = new ContextThemeWrapper(mContext, dualToneLightTheme);
         mDarkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme);
 
+        mWifiGroup = findViewById(R.id.wifi_group);
         mWifiIcon = findViewById(R.id.wifi_signal);
         mIn = findViewById(R.id.wifi_in);
         mOut = findViewById(R.id.wifi_out);
         mSignalSpacer = findViewById(R.id.wifi_signal_spacer);
         mAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
         mInoutContainer = findViewById(R.id.inout_container);
+
+        initDotView();
+    }
+
+    private void initDotView() {
+        mDotView = new StatusBarIconView(mContext, mSlot, null);
+        mDotView.setVisibleState(STATE_DOT);
+
+        int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size);
+        LayoutParams lp = new LayoutParams(width, width);
+        lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
+        addView(mDotView, lp);
     }
 
     public void applyWifiState(WifiIconState state) {
@@ -186,6 +239,8 @@
         }
         mIn.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint)));
         mOut.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint)));
+        mDotView.setDecorColor(tint);
+        mDotView.setIconColor(tint, false);
     }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
index ccab0d6..6383816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
@@ -21,6 +21,8 @@
 public interface StatusIconDisplayable extends DarkReceiver {
     String getSlot();
     void setStaticDrawableColor(int color);
+    void setDecorColor(int color);
+    void setVisibleState(int state);
     boolean isIconVisible();
     default boolean isIconBlocked() {
         return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 5a02d18..c1af1fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -21,10 +21,11 @@
 import android.content.Context;
 import android.view.View;
 import android.view.ViewStub;
-import android.widget.ProgressBar;
 
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
+
+import com.android.settingslib.users.UserManagerHelper;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBar;
 
@@ -35,10 +36,10 @@
     private final View mContainer;
     private final View mParent;
     private final UserGridRecyclerView mUserGridView;
-    private final ProgressBar mSwitchingUsers;
     private final int mShortAnimDuration;
     private final StatusBar mStatusBar;
-
+    private final UserManagerHelper mUserManagerHelper;
+    private int mCurrentForegroundUserId;
     private boolean mShowing;
 
     public FullscreenUserSwitcher(StatusBar statusBar, ViewStub containerStub, Context context) {
@@ -52,10 +53,11 @@
         mUserGridView.buildAdapter();
         mUserGridView.setUserSelectionListener(this::onUserSelected);
 
+        mUserManagerHelper = new UserManagerHelper(context);
+        updateCurrentForegroundUser();
+
         mShortAnimDuration = mContainer.getResources()
             .getInteger(android.R.integer.config_shortAnimTime);
-
-        mSwitchingUsers = mParent.findViewById(R.id.switching_users);
     }
 
     public void show() {
@@ -73,28 +75,44 @@
     }
 
     public void onUserSwitched(int newUserId) {
-        mParent.post(this::showOfflineAuthUi);
+        // The logic for foreground user change is needed here to exclude the reboot case. On
+        // reboot, system fires ACTION_USER_SWITCHED change from -1 to 0 user. This is not an actual
+        // user switch. We only want to trigger keyguard dismissal when foreground user changes.
+        if (foregroundUserChanged()) {
+            updateCurrentForegroundUser();
+            mParent.post(this::dismissKeyguard);
+        }
+    }
+
+    private boolean foregroundUserChanged() {
+        return mCurrentForegroundUserId != mUserManagerHelper.getForegroundUserId();
+    }
+
+    private void updateCurrentForegroundUser() {
+        mCurrentForegroundUserId = mUserManagerHelper.getForegroundUserId();
     }
 
     private void onUserSelected(UserGridRecyclerView.UserRecord record) {
         if (record.mIsForeground) {
-            showOfflineAuthUi();
+            dismissKeyguard();
             return;
         }
         toggleSwitchInProgress(true);
     }
 
-    private void showOfflineAuthUi() {
+    // Dismisses the keyguard and shows bouncer if authentication is necessary.
+    private void dismissKeyguard() {
         mStatusBar.executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
                 true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
     }
 
     private void toggleSwitchInProgress(boolean inProgress) {
         if (inProgress) {
-            crossFade(mSwitchingUsers, mContainer);
+            crossFade(mParent, mContainer);
         } else {
-            crossFade(mContainer, mSwitchingUsers);
+            crossFade(mContainer, mParent);
         }
+
     }
 
     private void crossFade(View incoming, View outgoing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/PageIndicator.java
deleted file mode 100644
index c830ff8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/PageIndicator.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.systemui.statusbar.car;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-
-import com.android.systemui.R;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Displays the dots underneath the ViewPager on the lock screen. This is really just a simplified
- * version of PagerTitleStrip. We don't inherit from there because it's impossible to bypass some
- * of the overriden logic in that class.
- */
-public class PageIndicator extends View {
-    private static final String TAG = "PageIndicator";
-    // These can be made a styleable attribute in the future if necessary.
-    private static final int SELECTED_COLOR = 0xFFF5F5F5;  // grey 100
-    private static final int UNSELECTED_COLOR = 0xFFBDBDBD;  // grey 400
-    private final PageListener mPageListener = new PageListener();
-
-    private ViewPager mPager;
-    private WeakReference<PagerAdapter> mWatchingAdapter;
-
-    private int mPageCount;
-    private int mCurrentPosition;
-    private Paint mPaint;
-    private int mRadius;
-    private int mStep;
-
-    public PageIndicator(Context context) {
-        super(context);
-        init();
-    }
-
-    public PageIndicator(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    private void init() {
-        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mPaint.setStyle(Paint.Style.FILL);
-        mRadius = getResources().getDimensionPixelSize(R.dimen.car_page_indicator_dot_diameter) / 2;
-        mStep = mRadius * 3;
-    }
-
-    public void setupWithViewPager(ViewPager pager) {
-        mPager = pager;
-
-        final PagerAdapter adapter = (PagerAdapter) pager.getAdapter();
-        pager.addOnPageChangeListener(mPageListener);
-        pager.addOnAdapterChangeListener(mPageListener);
-        updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
-        invalidate();
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        if (mPager != null) {
-            updateAdapter(mPager.getAdapter(), null);
-            mPager.removeOnPageChangeListener(mPageListener);
-            mPager.removeOnAdapterChangeListener(mPageListener);
-            mPager = null;
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-
-        // Don't draw anything unless there's multiple pages to scroll through.  No need to clear
-        // any previous dots, since onDraw provides a canvas that's already cleared.
-        if (mPageCount <= 1)
-            return;
-
-        int x = canvas.getWidth() / 2 - (mPageCount / 2) * mStep;
-        int y = canvas.getHeight() / 2;
-
-        for (int i = 0; i < mPageCount; i++) {
-            if (i == mCurrentPosition) {
-                mPaint.setColor(SELECTED_COLOR);
-            } else {
-                mPaint.setColor(UNSELECTED_COLOR);
-            }
-
-            canvas.drawCircle(x, y, mRadius, mPaint);
-            x += mStep;
-        }
-    }
-
-    void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
-        if (oldAdapter != null) {
-            oldAdapter.unregisterDataSetObserver(mPageListener);
-            mWatchingAdapter = null;
-        }
-
-        if (newAdapter != null) {
-            newAdapter.registerDataSetObserver(mPageListener);
-            mWatchingAdapter = new WeakReference<>(newAdapter);
-        }
-
-        updateDots();
-
-        if (mPager != null) {
-            requestLayout();
-        }
-    }
-
-    private <T> T getRef(WeakReference<T> weakRef) {
-        if (weakRef == null) {
-            return null;
-        }
-        return weakRef.get();
-    }
-
-    private void updateDots() {
-        PagerAdapter adapter = getRef(mWatchingAdapter);
-        if (adapter == null) {
-            return;
-        }
-
-        int count = adapter.getCount();
-        if (mPageCount == count) {
-            // Nothing to be done.
-            return;
-        }
-
-        mPageCount = count;
-        mCurrentPosition = 0;
-        invalidate();
-    }
-
-    private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
-            ViewPager.OnAdapterChangeListener {
-
-        @Override
-        public void onPageScrolled(int unused1, float unused2, int unused3) { }
-
-        @Override
-        public void onPageSelected(int position) {
-            if (mCurrentPosition == position) {
-                return;
-            }
-
-            if (mPageCount <= position) {
-                Log.e(TAG, "Position out of bounds, position=" + position + " size=" + mPageCount);
-                return;
-            }
-
-            mCurrentPosition = position;
-            invalidate();
-        }
-
-        @Override
-        public void onPageScrollStateChanged(int state) { }
-
-        @Override
-        public void onAdapterChanged(ViewPager viewPager, PagerAdapter oldAdapter,
-                PagerAdapter newAdapter) {
-            updateAdapter(oldAdapter, newAdapter);
-        }
-
-        @Override
-        public void onChanged() {
-            updateDots();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 5ad08ac..a171468 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -263,13 +263,13 @@
             GradientDrawable shape = new GradientDrawable();
             shape.setShape(GradientDrawable.RADIAL_GRADIENT);
             shape.setGradientRadius(1.0f);
-            shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
+            shape.setColor(mContext.getColor(R.color.car_grey_50));
             shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
             shape.draw(canvas);
 
             // Draw the letter in the center.
             Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
+            paint.setColor(mContext.getColor(R.color.car_grey_900));
             paint.setTextAlign(Align.CENTER);
             if (isAddUserText) {
                 paint.setTextSize(mRes.getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 28beb21..5f7b638 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -25,6 +25,7 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.android.internal.widget.NotificationActionListLayout;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
@@ -47,6 +48,7 @@
 
     private int mContentHeight;
     private int mMinHeightHint;
+    private NotificationActionListLayout mActions;
 
     protected NotificationTemplateViewWrapper(Context ctx, View view,
             ExpandableNotificationRow row) {
@@ -133,6 +135,7 @@
             mProgressBar = null;
         }
         mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
+        mActions = mView.findViewById(com.android.internal.R.id.actions);
         mReplyAction = mView.findViewById(com.android.internal.R.id.reply_icon_action);
     }
 
@@ -284,4 +287,13 @@
                     - getHeaderTranslation());
         }
     }
+
+    @Override
+    public int getExtraMeasureHeight() {
+        int extra = 0;
+        if (mActions != null) {
+            extra = mActions.getExtraMeasureHeight();
+        }
+        return extra + super.getExtraMeasureHeight();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 873f088..b09df15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -205,4 +205,12 @@
 
     public void setHeaderVisibleAmount(float headerVisibleAmount) {
     }
+
+    /**
+     * Get the extra height that needs to be added to this view, such that it can be measured
+     * normally.
+     */
+    public int getExtraMeasureHeight() {
+        return 0;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 48540b1..824960e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -198,8 +198,7 @@
 
     public void addDemoWifiView(WifiIconState state) {
         Log.d(TAG, "addDemoWifiView: ");
-        StatusBarWifiView view = StatusBarWifiView.fromContext(mContext);
-        view.setSlot(state.slot);
+        StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, state.slot);
 
         int viewIndex = getChildCount();
         // If we have mobile views, put wifi before them
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index b817809..9787d73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -205,12 +205,6 @@
     }
 
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        updateLayoutConsideringCutout();
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         mLayoutState = LAYOUT_NONE;
         if (updateLayoutConsideringCutout()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 94e004b..1ba37a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -163,6 +163,7 @@
                 StatusBarIconHolder holder) {
             StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
             view.setStaticDrawableColor(mColor);
+            view.setDecorColor(mColor);
         }
 
         public void setTint(int color) {
@@ -172,6 +173,7 @@
                 if (child instanceof StatusIconDisplayable) {
                     StatusIconDisplayable icon = (StatusIconDisplayable) child;
                     icon.setStaticDrawableColor(mColor);
+                    icon.setDecorColor(mColor);
                 }
             }
         }
@@ -289,8 +291,7 @@
         }
 
         private StatusBarWifiView onCreateStatusBarWifiView(String slot) {
-            StatusBarWifiView view = StatusBarWifiView.fromContext(mContext);
-            view.setSlot(slot);
+            StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, slot);
             return view;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 255e10e..c97c8eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -16,30 +16,57 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
+
 import android.annotation.Nullable;
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
 import android.util.AttributeSet;
 import android.util.Log;
 
 import android.view.View;
+import android.view.ViewGroup;
 import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.stack.ViewState;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 /**
  * A container for Status bar system icons. Limits the number of system icons and handles overflow
- * similar to NotificationIconController. Can be used to layout nested StatusIconContainers
+ * similar to {@link NotificationIconContainer}.
  *
- * Children are expected to be of type StatusBarIconView.
+ * Children are expected to implement {@link StatusIconDisplayable}
  */
 public class StatusIconContainer extends AlphaOptimizedLinearLayout {
 
     private static final String TAG = "StatusIconContainer";
     private static final boolean DEBUG = false;
-    private static final int MAX_ICONS = 5;
+    private static final boolean DEBUG_OVERFLOW = false;
+    // Max 5 status icons including battery
+    private static final int MAX_ICONS = 4;
     private static final int MAX_DOTS = 3;
 
+    private int mDotPadding;
+    private int mStaticDotDiameter;
+    private int mUnderflowWidth;
+    private int mUnderflowStart = 0;
+    // Whether or not we can draw into the underflow space
+    private boolean mNeedsUnderflow;
+    // Individual StatusBarIconViews draw their etc dots centered in this width
+    private int mIconDotFrameWidth;
+    private boolean mShouldRestrictIcons = true;
+    // Used to count which states want to be visible during layout
+    private ArrayList<StatusIconState> mLayoutStates = new ArrayList<>();
+    // So we can count and measure properly
+    private ArrayList<View> mMeasureViews = new ArrayList<>();
+
     public StatusIconContainer(Context context) {
         this(context, null);
     }
@@ -49,6 +76,27 @@
     }
 
     @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        setWillNotDraw(!DEBUG_OVERFLOW);
+        initDimens();
+    }
+
+    public void setShouldRestrictIcons(boolean should) {
+        mShouldRestrictIcons = should;
+    }
+
+    private void initDimens() {
+        // This is the same value that StatusBarIconView uses
+        mIconDotFrameWidth = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_icon_size);
+        mDotPadding = getResources().getDimensionPixelSize(R.dimen.overflow_icon_dot_padding);
+        int radius = getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius);
+        mStaticDotDiameter = 2 * radius;
+        mUnderflowWidth = mIconDotFrameWidth + 2 * (mStaticDotDiameter + mDotPadding);
+    }
+
+    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         float midY = getHeight() / 2.0f;
 
@@ -67,23 +115,80 @@
     }
 
     @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        if (DEBUG_OVERFLOW) {
+            Paint paint = new Paint();
+            paint.setStyle(Style.STROKE);
+            paint.setColor(Color.RED);
+
+            // Show bounding box
+            canvas.drawRect(getPaddingStart(), 0, getWidth() - getPaddingEnd(), getHeight(), paint);
+
+            // Show etc box
+            paint.setColor(Color.GREEN);
+            canvas.drawRect(
+                    mUnderflowStart, 0, mUnderflowStart + mUnderflowWidth, getHeight(), paint);
+        }
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-        int width = MeasureSpec.getSize(widthMeasureSpec);
-        int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
-
+        mMeasureViews.clear();
+        int mode = MeasureSpec.getMode(widthMeasureSpec);
+        final int width = MeasureSpec.getSize(widthMeasureSpec);
         final int count = getChildCount();
-        // Measure all children so that they report the correct width
+        // Collect all of the views which want to be laid out
         for (int i = 0; i < count; i++) {
-            measureChild(getChildAt(i), widthSpec, heightMeasureSpec);
+            StatusIconDisplayable icon = (StatusIconDisplayable) getChildAt(i);
+            if (icon.isIconVisible() && !icon.isIconBlocked()) {
+                mMeasureViews.add((View) icon);
+            }
+        }
+
+        int visibleCount = mMeasureViews.size();
+        int maxVisible = visibleCount <= MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;
+        int totalWidth = getPaddingStart() + getPaddingEnd();
+        boolean trackWidth = true;
+
+        // Measure all children so that they report the correct width
+        int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
+        mNeedsUnderflow = mShouldRestrictIcons && visibleCount > MAX_ICONS;
+        for (int i = 0; i < mMeasureViews.size(); i++) {
+            // Walking backwards
+            View child = mMeasureViews.get(visibleCount - i - 1);
+            measureChild(child, childWidthSpec, heightMeasureSpec);
+            if (mShouldRestrictIcons) {
+                if (i < maxVisible && trackWidth) {
+                    totalWidth += getViewTotalMeasuredWidth(child);
+                } else if (trackWidth) {
+                    // We've hit the icon limit; add space for dots
+                    totalWidth += mUnderflowWidth;
+                    trackWidth = false;
+                }
+            } else {
+                totalWidth += getViewTotalMeasuredWidth(child);
+            }
+        }
+
+        if (mode == MeasureSpec.EXACTLY) {
+            if (!mNeedsUnderflow && totalWidth > width) {
+                mNeedsUnderflow = true;
+            }
+            setMeasuredDimension(width, MeasureSpec.getSize(heightMeasureSpec));
+        } else {
+            if (mode == MeasureSpec.AT_MOST && totalWidth > width) {
+                mNeedsUnderflow = true;
+                totalWidth = width;
+            }
+            setMeasuredDimension(totalWidth, MeasureSpec.getSize(heightMeasureSpec));
         }
     }
 
     @Override
     public void onViewAdded(View child) {
         super.onViewAdded(child);
-        ViewState vs = new ViewState();
+        StatusIconState vs = new StatusIconState();
         child.setTag(R.id.status_bar_view_state_tag, vs);
     }
 
@@ -97,6 +202,7 @@
      * Layout is happening from end -> start
      */
     private void calculateIconTranslations() {
+        mLayoutStates.clear();
         float width = getWidth() - getPaddingEnd();
         float translationX = width;
         float contentStart = getPaddingStart();
@@ -106,45 +212,57 @@
         if (DEBUG) android.util.Log.d(TAG, "calculateIconTransitions: start=" + translationX
                 + " width=" + width);
 
-        //TODO: Dots
+        // Collect all of the states which want to be visible
         for (int i = childCount - 1; i >= 0; i--) {
             View child = getChildAt(i);
-            if (!(child instanceof StatusIconDisplayable)) {
-                if (DEBUG) Log.d(TAG, "skipping child (wrong type)");
-                continue;
-            }
-
             StatusIconDisplayable iconView = (StatusIconDisplayable) child;
-
-            ViewState childState = getViewStateFromChild(child);
-            if (childState == null ) {
-                if (DEBUG) Log.d(TAG, "skipping child (" + iconView.getSlot() + ") no ViewState");
-                continue;
-            }
+            StatusIconState childState = getViewStateFromChild(child);
 
             if (!iconView.isIconVisible() || iconView.isIconBlocked()) {
-                childState.hidden = true;
+                childState.visibleState = STATE_HIDDEN;
                 if (DEBUG) Log.d(TAG, "skipping child (" + iconView.getSlot() + ") not visible");
                 continue;
             }
 
-            childState.xTranslation = translationX - child.getWidth();
+            childState.visibleState = STATE_ICON;
+            childState.xTranslation = translationX - getViewTotalWidth(child);
+            mLayoutStates.add(0, childState);
 
-            if (childState.xTranslation < contentStart) {
-                if (firstUnderflowIndex == -1) {
-                    firstUnderflowIndex = i;
-                }
+            translationX -= getViewTotalWidth(child);
+        }
+
+        // Show either 1-4 dots, or 3 dots + overflow
+        int totalVisible = mLayoutStates.size();
+        int maxVisible = totalVisible <= MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;
+
+        mUnderflowStart = 0;
+        int visible = 0;
+        firstUnderflowIndex = -1;
+        for (int i = totalVisible - 1; i >= 0; i--) {
+            StatusIconState state = mLayoutStates.get(i);
+            // Allow room for underflow if we found we need it in onMeasure
+            if (mNeedsUnderflow && (state.xTranslation < (contentStart + mUnderflowWidth))||
+                    (mShouldRestrictIcons && visible >= maxVisible)) {
+                firstUnderflowIndex = i;
+                break;
             }
-
-            translationX -= child.getWidth();
+            mUnderflowStart = (int) Math.max(contentStart, state.xTranslation - mUnderflowWidth);
+            visible++;
         }
 
         if (firstUnderflowIndex != -1) {
-            for (int i = 0; i <= firstUnderflowIndex; i++) {
-                View child = getChildAt(i);
-                ViewState vs = getViewStateFromChild(child);
-                if (vs != null) {
-                    vs.hidden = true;
+            int totalDots = 0;
+            int dotWidth = mStaticDotDiameter + mDotPadding;
+            int dotOffset = mUnderflowStart + mUnderflowWidth - mIconDotFrameWidth;
+            for (int i = firstUnderflowIndex; i >= 0; i--) {
+                StatusIconState state = mLayoutStates.get(i);
+                if (totalDots < MAX_DOTS) {
+                    state.xTranslation = dotOffset;
+                    state.visibleState = STATE_DOT;
+                    dotOffset -= dotWidth;
+                    totalDots++;
+                } else {
+                    state.visibleState = STATE_HIDDEN;
                 }
             }
         }
@@ -153,7 +271,7 @@
         if (isLayoutRtl()) {
             for (int i = 0; i < childCount; i++) {
                 View child = getChildAt(i);
-                ViewState state = getViewStateFromChild(child);
+                StatusIconState state = getViewStateFromChild(child);
                 state.xTranslation = width - state.xTranslation - child.getWidth();
             }
         }
@@ -162,7 +280,7 @@
     private void applyIconStates() {
         for (int i = 0; i < getChildCount(); i++) {
             View child = getChildAt(i);
-            ViewState vs = getViewStateFromChild(child);
+            StatusIconState vs = getViewStateFromChild(child);
             if (vs != null) {
                 vs.applyToView(child);
             }
@@ -172,7 +290,7 @@
     private void resetViewStates() {
         for (int i = 0; i < getChildCount(); i++) {
             View child = getChildAt(i);
-            ViewState vs = getViewStateFromChild(child);
+            StatusIconState vs = getViewStateFromChild(child);
             if (vs == null) {
                 continue;
             }
@@ -187,7 +305,29 @@
         }
     }
 
-    private static @Nullable ViewState getViewStateFromChild(View child) {
-        return (ViewState) child.getTag(R.id.status_bar_view_state_tag);
+    private static @Nullable StatusIconState getViewStateFromChild(View child) {
+        return (StatusIconState) child.getTag(R.id.status_bar_view_state_tag);
+    }
+
+    private static int getViewTotalMeasuredWidth(View child) {
+        return child.getMeasuredWidth() + child.getPaddingStart() + child.getPaddingEnd();
+    }
+
+    private static int getViewTotalWidth(View child) {
+        return child.getWidth() + child.getPaddingStart() + child.getPaddingEnd();
+    }
+
+    public static class StatusIconState extends ViewState {
+        /// StatusBarIconView.STATE_*
+        public int visibleState = STATE_ICON;
+
+        @Override
+        public void applyToView(View view) {
+            if (view instanceof  StatusIconDisplayable) {
+                StatusIconDisplayable icon = (StatusIconDisplayable) view;
+                icon.setVisibleState(visibleState);
+            }
+            super.applyToView(view);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 00874e3..e801607 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -45,10 +45,8 @@
 import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ColorDrawable;
-import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
-import android.media.MediaPlayer;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
@@ -132,8 +130,8 @@
     private final AccessibilityManagerWrapper mAccessibilityMgr;
     private final Object mSafetyWarningLock = new Object();
     private final Accessibility mAccessibility = new Accessibility();
-    private final ColorStateList mActiveSliderTint;
-    private final ColorStateList mInactiveSliderTint;
+    private final ColorStateList mActiveTint;
+    private final ColorStateList mInactiveTint;
     private final Vibrator mVibrator;
 
     private boolean mShowing;
@@ -152,8 +150,8 @@
         mController = Dependency.get(VolumeDialogController.class);
         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
         mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
-        mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
-        mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
+        mActiveTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
+        mInactiveTint = loadColorStateList(R.color.volume_slider_inactive);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
     }
@@ -614,7 +612,7 @@
             final boolean shouldBeVisible = shouldBeVisibleH(row, activeRow);
             Util.setVisOrGone(row.view, shouldBeVisible);
             if (row.view.isShown()) {
-                updateVolumeRowSliderTintH(row, isActive);
+                updateVolumeRowTintH(row, isActive);
             }
         }
     }
@@ -848,21 +846,22 @@
         updateVolumeRowSliderH(row, enableSlider, vlevel);
     }
 
-    private void updateVolumeRowSliderTintH(VolumeRow row, boolean isActive) {
+    private void updateVolumeRowTintH(VolumeRow row, boolean isActive) {
         if (isActive) {
             row.slider.requestFocus();
         }
-        final ColorStateList tint = isActive && row.slider.isEnabled() ? mActiveSliderTint
-                : mInactiveSliderTint;
-        if (tint == row.cachedSliderTint) return;
-        row.cachedSliderTint = tint;
+        final ColorStateList tint = isActive && row.slider.isEnabled() ? mActiveTint
+                : mInactiveTint;
+        if (tint == row.cachedTint) return;
         row.slider.setProgressTintList(tint);
         row.slider.setThumbTintList(tint);
+        row.icon.setImageTintList(tint);
+        row.cachedTint = tint;
     }
 
     private void updateVolumeRowSliderH(VolumeRow row, boolean enable, int vlevel) {
         row.slider.setEnabled(enable);
-        updateVolumeRowSliderTintH(row, row.stream == mActiveStream);
+        updateVolumeRowTintH(row, row.stream == mActiveStream);
         if (row.tracking) {
             return;  // don't update if user is sliding
         }
@@ -1234,7 +1233,7 @@
         private int iconMuteRes;
         private boolean important;
         private boolean defaultStream;
-        private ColorStateList cachedSliderTint;
+        private ColorStateList cachedTint;
         private int iconState;  // from Events
         private ObjectAnimator anim;  // slider progress animation for non-touch-related updates
         private int animTargetProgress;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 067566d..b1cb2fe 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -415,12 +415,23 @@
             return null;
         }
 
-        // If the app has strict background restrictions, we treat any service
-        // start analogously to the legacy-app forced-restrictions case.
+        // If we're starting indirectly (e.g. from PendingIntent), figure out whether
+        // we're launching into an app in a background state.
+        final int uidState = mAm.getUidStateLocked(r.appInfo.uid);
+        if (DEBUG_SERVICE) {
+            Slog.v(TAG_SERVICE, "Uid state " + uidState + " indirect starting " + r.shortName);
+        }
+        final boolean bgLaunch = (uidState >
+                ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+
+        // If the app has strict background restrictions, we treat any bg service
+        // start analogously to the legacy-app forced-restrictions case, regardless
+        // of its target SDK version.
         boolean forcedStandby = false;
-        if (appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
+        if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
             if (DEBUG_FOREGROUND_SERVICE) {
-                Slog.d(TAG, "Forcing bg-only service start only for " + r.shortName);
+                Slog.d(TAG, "Forcing bg-only service start only for " + r.shortName
+                        + " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
             }
             forcedStandby = true;
         }
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
new file mode 100644
index 0000000..e34ee63
--- /dev/null
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 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 com.android.server.am;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.GradientDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
+ * screen immediately after the dialog shows so that the user is informed that something is
+ * happening in the background rather than just freeze the screen and not know if the user-switch
+ * affordance was being handled.
+ *
+ */
+final class CarUserSwitchingDialog extends UserSwitchingDialog {
+    private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
+
+    public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
+        UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
+        String switchingToSystemUserMessage) {
+        super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
+            switchingToSystemUserMessage);
+
+        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+    }
+
+    @Override
+    void inflateContent() {
+        // Set up the dialog contents
+        setCancelable(false);
+        Resources res = getContext().getResources();
+        // Custom view due to alignment and font size requirements
+        View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
+            null);
+
+        ((ImageView) view.findViewById(R.id.user_loading_avatar))
+            .setImageBitmap(getDefaultUserIcon(mNewUser));
+        ((TextView) view.findViewById(R.id.user_loading))
+            .setText(res.getString(R.string.car_loading_profile));
+        setView(view);
+    }
+
+    /**
+     * Returns the default user icon.  This icon is a circle with a letter in it.  The letter is
+     * the first character in the username.
+     *
+     * @param userInfo the profile of the user for which the icon should be created
+     */
+    private Bitmap getDefaultUserIcon(UserInfo userInfo) {
+        Resources res = mContext.getResources();
+        int mPodImageAvatarWidth = res.getDimensionPixelSize(
+            R.dimen.car_fullscreen_user_pod_image_avatar_width);
+        int mPodImageAvatarHeight = res.getDimensionPixelSize(
+            R.dimen.car_fullscreen_user_pod_image_avatar_height);
+        CharSequence displayText = userInfo.name.subSequence(0, 1);
+        Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
+            Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(out);
+
+        // Draw the circle background.
+        GradientDrawable shape = new GradientDrawable();
+        shape.setShape(GradientDrawable.RADIAL_GRADIENT);
+        shape.setGradientRadius(1.0f);
+        shape.setColor(mContext.getColor(R.color.car_user_switcher_user_image_bgcolor));
+        shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
+        shape.draw(canvas);
+
+        // Draw the letter in the center.
+        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        paint.setColor(mContext.getColor(R.color.car_user_switcher_user_image_fgcolor));
+        paint.setTextAlign(Align.CENTER);
+        paint.setTextSize(res.getDimensionPixelSize(
+            R.dimen.car_fullscreen_user_pod_icon_text_size));
+
+        Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
+        // The Y coordinate is measured by taking half the height of the pod, but that would
+        // draw the character putting the bottom of the font in the middle of the pod.  To
+        // correct this, half the difference between the top and bottom distance metrics of the
+        // font gives the offset of the font.  Bottom is a positive value, top is negative, so
+        // the different is actually a sum.  The "half" operation is then factored out.
+        canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
+            (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
+
+        return out;
+    }
+}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index fecb934..060d4c8 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -79,6 +79,7 @@
 import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.IntArray;
+import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -86,6 +87,7 @@
 import android.util.TimingsTraceLog;
 import android.util.proto.ProtoOutputStream;
 
+import android.view.Window;
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -2177,9 +2179,18 @@
 
         void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
                 String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
-            Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
+            Dialog d;
+            if (!mService.mContext.getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+                d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
                     true /* above system */, switchingFromSystemUserMessage,
                     switchingToSystemUserMessage);
+            } else {
+                d = new CarUserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
+                    true /* above system */, switchingFromSystemUserMessage,
+                    switchingToSystemUserMessage);
+            }
+
             d.show();
         }
 
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index afcba3b..98f5557 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -39,7 +39,7 @@
  * in the background rather than just freeze the screen and not know if the user-switch affordance
  * was being handled.
  */
-final class UserSwitchingDialog extends AlertDialog
+class UserSwitchingDialog extends AlertDialog
         implements ViewTreeObserver.OnWindowShownListener {
     private static final String TAG = "ActivityManagerUserSwitchingDialog";
 
@@ -51,53 +51,69 @@
     private static final int MSG_START_USER = 1;
     @GuardedBy("this")
     private boolean mStartedUser;
+    final protected UserInfo mOldUser;
+    final protected UserInfo mNewUser;
+    final private String mSwitchingFromSystemUserMessage;
+    final private String mSwitchingToSystemUserMessage;
+    final protected Context mContext;
 
     public UserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
             UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
             String switchingToSystemUserMessage) {
         super(context);
 
+        mContext = context;
         mService = service;
         mUserId = newUser.id;
+        mOldUser = oldUser;
+        mNewUser = newUser;
+        mSwitchingFromSystemUserMessage = switchingFromSystemUserMessage;
+        mSwitchingToSystemUserMessage = switchingToSystemUserMessage;
 
+        inflateContent();
+
+        if (aboveSystem) {
+            getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+        }
+
+        WindowManager.LayoutParams attrs = getWindow().getAttributes();
+        attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
+            WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        getWindow().setAttributes(attrs);
+    }
+
+    void inflateContent() {
         // Set up the dialog contents
         setCancelable(false);
         Resources res = getContext().getResources();
         // Custom view due to alignment and font size requirements
-        View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog, null);
+        View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog,
+            null);
 
         String viewMessage = null;
-        if (UserManager.isSplitSystemUser() && newUser.id == UserHandle.USER_SYSTEM) {
-            viewMessage = res.getString(R.string.user_logging_out_message, oldUser.name);
-        } else if (UserManager.isDeviceInDemoMode(context)) {
-            if (oldUser.isDemo()) {
+        if (UserManager.isSplitSystemUser() && mNewUser.id == UserHandle.USER_SYSTEM) {
+            viewMessage = res.getString(R.string.user_logging_out_message, mOldUser.name);
+        } else if (UserManager.isDeviceInDemoMode(mContext)) {
+            if (mOldUser.isDemo()) {
                 viewMessage = res.getString(R.string.demo_restarting_message);
             } else {
                 viewMessage = res.getString(R.string.demo_starting_message);
             }
         } else {
-            if (oldUser.id == UserHandle.USER_SYSTEM) {
-                viewMessage = switchingFromSystemUserMessage;
-            } else if (newUser.id == UserHandle.USER_SYSTEM) {
-                viewMessage = switchingToSystemUserMessage;
+            if (mOldUser.id == UserHandle.USER_SYSTEM) {
+                viewMessage = mSwitchingFromSystemUserMessage;
+            } else if (mNewUser.id == UserHandle.USER_SYSTEM) {
+                viewMessage = mSwitchingToSystemUserMessage;
             }
 
             // If switchingFromSystemUserMessage or switchingToSystemUserMessage is null, fallback
             // to system message.
             if (viewMessage == null) {
-                viewMessage = res.getString(R.string.user_switching_message, newUser.name);
+                viewMessage = res.getString(R.string.user_switching_message, mNewUser.name);
             }
         }
         ((TextView) view.findViewById(R.id.message)).setText(viewMessage);
         setView(view);
-
-        if (aboveSystem) {
-            getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-        }
-        WindowManager.LayoutParams attrs = getWindow().getAttributes();
-        attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
-                WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-        getWindow().setAttributes(attrs);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 567eaaa..1faa9f7 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -349,7 +349,6 @@
                 .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion))
                 .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
                 .setCounterId(counterId)
-                .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
                 .setServerParams(vaultHandle)
                 .setKeyChainProtectionParams(metadataList)
                 .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys))
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java
index f789155..b486834 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java
@@ -132,8 +132,7 @@
                     break;
 
                 case TAG_BACKEND_PUBLIC_KEY:
-                    builder.setTrustedHardwarePublicKey(
-                            readBlobTag(parser, TAG_BACKEND_PUBLIC_KEY));
+                    // Unused
                     break;
 
                 case TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST:
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java
index ff30ecd..0f2c2fc 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java
@@ -35,7 +35,7 @@
     static final String TAG_RECOVERY_KEY_MATERIAL = "recoveryKeyMaterial";
     static final String TAG_SERVER_PARAMS = "serverParams";
     static final String TAG_TRUSTED_HARDWARE_CERT_PATH = "thmCertPath";
-    static final String TAG_BACKEND_PUBLIC_KEY = "backendPublicKey";
+    static final String TAG_BACKEND_PUBLIC_KEY = "backendPublicKey"; // Deprecated.
 
     static final String TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST =
             "keyChainProtectionParamsList";
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java
index 17a16bf..235df69 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java
@@ -162,10 +162,6 @@
         writePropertyTag(xmlSerializer, TAG_SERVER_PARAMS, keyChainSnapshot.getServerParams());
         writePropertyTag(xmlSerializer, TAG_TRUSTED_HARDWARE_CERT_PATH,
                 keyChainSnapshot.getTrustedHardwareCertPath());
-        if (keyChainSnapshot.getTrustedHardwarePublicKey() != null) {
-            writePropertyTag(xmlSerializer, TAG_BACKEND_PUBLIC_KEY,
-                    keyChainSnapshot.getTrustedHardwarePublicKey());
-        }
     }
 
     private static void writePropertyTag(
diff --git a/services/core/java/com/android/server/media/MediaUpdateService.java b/services/core/java/com/android/server/media/MediaUpdateService.java
index f38b353..af06d15 100644
--- a/services/core/java/com/android/server/media/MediaUpdateService.java
+++ b/services/core/java/com/android/server/media/MediaUpdateService.java
@@ -23,11 +23,14 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.media.IMediaExtractorUpdateService;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.Handler;
 import android.os.PatternMatcher;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
 import com.android.server.SystemService;
@@ -36,7 +39,8 @@
 public class MediaUpdateService extends SystemService {
     private static final String TAG = "MediaUpdateService";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String MEDIA_UPDATE_PACKAGE_NAME = "com.android.media.update";
+    private static final String MEDIA_UPDATE_PACKAGE_NAME =
+            SystemProperties.get("ro.mediacomponents.package");
     private static final String EXTRACTOR_UPDATE_SERVICE_NAME = "media.extractor.update";
 
     private IMediaExtractorUpdateService mMediaExtractorUpdateService;
@@ -49,7 +53,8 @@
 
     @Override
     public void onStart() {
-        if ("userdebug".equals(android.os.Build.TYPE) || "eng".equals(android.os.Build.TYPE)) {
+        if (("userdebug".equals(android.os.Build.TYPE) || "eng".equals(android.os.Build.TYPE))
+                && !TextUtils.isEmpty(MEDIA_UPDATE_PACKAGE_NAME)) {
             connect();
             registerBroadcastReceiver();
         }
@@ -133,6 +138,12 @@
         } catch (Exception e) {
             Slog.v(TAG, "package '" + MEDIA_UPDATE_PACKAGE_NAME + "' not installed");
         }
+        if (packageInfo != null && Build.VERSION.SDK_INT != packageInfo.targetSdkVersion) {
+            Slog.w(TAG, "This update package is not for this platform version. Ignoring. "
+                    + "platform:" + Build.VERSION.SDK_INT
+                    + " targetSdk:" + packageInfo.targetSdkVersion);
+            pluginsAvailable = false;
+        }
         loadExtractorPlugins(
                 (packageInfo != null && pluginsAvailable) ? packageInfo.sourceDir : "");
     }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4e848f8..e3ff72b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -286,6 +286,16 @@
     private long mPersistThreshold = 2 * MB_IN_BYTES;
     private long mGlobalAlertBytes;
 
+    private static final long POLL_RATE_LIMIT_MS = 15_000;
+
+    private long mLastStatsSessionPoll;
+
+    /** Map from UID to number of opened sessions */
+    @GuardedBy("mOpenSessionCallsPerUid")
+    private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
+
+    private final static int DUMP_STATS_SESSION_COUNT = 20;
+
     private static @NonNull File getDefaultSystemDir() {
         return new File(Environment.getDataDirectory(), "system");
     }
@@ -509,10 +519,31 @@
         return openSessionInternal(flags, callingPackage);
     }
 
+    private boolean isRateLimitedForPoll(int callingUid) {
+        if (callingUid == android.os.Process.SYSTEM_UID) {
+            return false;
+        }
+
+        final long lastCallTime;
+        final long now = SystemClock.elapsedRealtime();
+        synchronized (mOpenSessionCallsPerUid) {
+            int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
+            mOpenSessionCallsPerUid.put(callingUid, calls + 1);
+            lastCallTime = mLastStatsSessionPoll;
+            mLastStatsSessionPoll = now;
+        }
+
+        return now - lastCallTime < POLL_RATE_LIMIT_MS;
+    }
+
     private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
         assertBandwidthControlEnabled();
 
-        if ((flags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) {
+        final int callingUid = Binder.getCallingUid();
+        final int usedFlags = isRateLimitedForPoll(callingUid)
+                ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
+                : flags;
+        if ((usedFlags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) {
             final long ident = Binder.clearCallingIdentity();
             try {
                 performPoll(FLAG_PERSIST_ALL);
@@ -525,7 +556,7 @@
         // for its lifetime; when caller closes only weak references remain.
 
         return new INetworkStatsSession.Stub() {
-            private final int mCallingUid = Binder.getCallingUid();
+            private final int mCallingUid = callingUid;
             private final String mCallingPackage = callingPackage;
             private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
                     callingPackage);
@@ -559,20 +590,20 @@
             @Override
             public NetworkStats getDeviceSummaryForNetwork(
                     NetworkTemplate template, long start, long end) {
-                return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel,
+                return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
                         mCallingUid);
             }
 
             @Override
             public NetworkStats getSummaryForNetwork(
                     NetworkTemplate template, long start, long end) {
-                return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel,
+                return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
                         mCallingUid);
             }
 
             @Override
             public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
-                return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel,
+                return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
                         mCallingUid);
             }
 
@@ -1461,6 +1492,30 @@
             }
             pw.decreaseIndent();
 
+            // Get the top openSession callers
+            final SparseIntArray calls;
+            synchronized (mOpenSessionCallsPerUid) {
+                calls = mOpenSessionCallsPerUid.clone();
+            }
+
+            final int N = calls.size();
+            final long[] values = new long[N];
+            for (int j = 0; j < N; j++) {
+                values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
+            }
+            Arrays.sort(values);
+
+            pw.println("Top openSession callers (uid=count):");
+            pw.increaseIndent();
+            final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
+            for (int j = N - 1; j >= end; j--) {
+                final int uid = (int) (values[j] & 0xffffffff);
+                final int count = (int) (values[j] >> 32);
+                pw.print(uid); pw.print("="); pw.println(count);
+            }
+            pw.decreaseIndent();
+            pw.println();
+
             pw.println("Dev stats:");
             pw.increaseIndent();
             mDevRecorder.dumpLocked(pw, fullHistory);
diff --git a/services/core/java/com/android/server/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java
index d42c7c1..4001b90 100644
--- a/services/core/java/com/android/server/notification/CalendarTracker.java
+++ b/services/core/java/com/android/server/notification/CalendarTracker.java
@@ -30,6 +30,7 @@
 import android.service.notification.ZenModeConfig.EventInfo;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 
 import java.io.PrintWriter;
 import java.util.Date;
@@ -161,6 +162,8 @@
                     }
                 }
             }
+        } catch (Exception e) {
+            Slog.w(TAG, "error reading calendar", e);
         } finally {
             if (cursor != null) {
                 cursor.close();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 55f51c2..c6886da 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2394,6 +2394,12 @@
         }
 
         @Override
+        public int getBlockedAppCount(int userId) {
+            checkCallerIsSystem();
+            return mRankingHelper.getBlockedAppCount(userId);
+        }
+
+        @Override
         public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException {
             checkCallerIsSystem();
 
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index c2ec79b..89bd660 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -1011,6 +1011,21 @@
         return blockedCount;
     }
 
+    public int getBlockedAppCount(int userId) {
+        int count = 0;
+        synchronized (mRecords) {
+            final int N = mRecords.size();
+            for (int i = 0; i < N; i++) {
+                final Record r = mRecords.valueAt(i);
+                if (userId == UserHandle.getUserId(r.uid)
+                        && r.importance == IMPORTANCE_NONE) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
     /**
      * Sets importance.
      */
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java
index 2f4da86..07c6203 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java
@@ -45,7 +45,6 @@
     private static final int MAX_ATTEMPTS = 21;
     private static final byte[] SERVER_PARAMS = new byte[] { 8, 2, 4 };
     private static final byte[] KEY_BLOB = new byte[] { 124, 53, 53, 53 };
-    private static final byte[] PUBLIC_KEY_BLOB = new byte[] { 6, 6, 6, 6, 6, 6, 7 };
     private static final CertPath CERT_PATH = TestData.CERT_PATH_1;
     private static final int SECRET_TYPE = KeyChainProtectionParams.TYPE_LOCKSCREEN;
     private static final int LOCK_SCREEN_UI = KeyChainProtectionParams.UI_FORMAT_PASSWORD;
@@ -94,11 +93,6 @@
     }
 
     @Test
-    public void roundTrip_persistsBackendPublicKey() throws Exception {
-        assertThat(roundTrip().getTrustedHardwarePublicKey()).isEqualTo(PUBLIC_KEY_BLOB);
-    }
-
-    @Test
     public void roundTrip_persistsParamsList() throws Exception {
         assertThat(roundTrip().getKeyChainProtectionParams()).hasSize(1);
     }
@@ -201,7 +195,6 @@
                 .setKeyChainProtectionParams(createKeyChainProtectionParamsList())
                 .setWrappedApplicationKeys(createKeys())
                 .setTrustedHardwareCertPath(CERT_PATH)
-                .setTrustedHardwarePublicKey(PUBLIC_KEY_BLOB)
                 .build();
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 78aa965..bda6b8a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -1733,4 +1733,24 @@
         mHelper.createNotificationChannel(PKG, 1000, update, true, false);
         assertFalse(mHelper.getNotificationChannel(PKG, 1000, "A", false).canBypassDnd());
     }
+
+    @Test
+    public void testGetBlockedAppCount_noApps() {
+        assertEquals(0, mHelper.getBlockedAppCount(0));
+    }
+
+    @Test
+    public void testGetBlockedAppCount_noAppsForUserId() {
+        mHelper.setEnabled(PKG, 100, false);
+        assertEquals(0, mHelper.getBlockedAppCount(9));
+    }
+
+    @Test
+    public void testGetBlockedAppCount_appsForUserId() {
+        mHelper.setEnabled(PKG, 1020, false);
+        mHelper.setEnabled(PKG, 1030, false);
+        mHelper.setEnabled(PKG, 1060, false);
+        mHelper.setEnabled(PKG, 1000, true);
+        assertEquals(3, mHelper.getBlockedAppCount(0));
+    }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e244131..a6ece89 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1013,11 +1013,13 @@
     /**
      * Unconditionally override the carrier name string using #KEY_CARRIER_NAME_STRING.
      *
-     * If true, then the carrier display name will be #KEY_CARRIER_NAME_STRING, unconditionally.
+     * If true, then the carrier name string will be #KEY_CARRIER_NAME_STRING, unconditionally.
      *
      * <p>If false, then the override will be performed conditionally and the
      * #KEY_CARRIER_NAME_STRING will have the lowest-precedence; it will only be used in the event
-     * that the name string would otherwise be empty, allowing it to serve as a last-resort.
+     * that the name string would otherwise be empty, allowing it to serve as a last-resort. If
+     * used, this value functions in place of the SPN on any/all ICC records for the corresponding
+     * subscription.
      */
     public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
 
@@ -1687,6 +1689,7 @@
      * Controls if the device should automatically notify the user as they reach
      * their cellular data warning. When set to {@code false} the carrier is
      * expected to have implemented their own notification mechanism.
+     * @hide
      */
     public static final String KEY_DATA_WARNING_NOTIFICATION_BOOL =
             "data_warning_notification_bool";
@@ -1709,6 +1712,7 @@
      * Controls if the device should automatically notify the user as they reach
      * their cellular data limit. When set to {@code false} the carrier is
      * expected to have implemented their own notification mechanism.
+     * @hide
      */
     public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL =
             "data_limit_notification_bool";
@@ -1717,6 +1721,7 @@
      * Controls if the device should automatically notify the user when rapid
      * cellular data usage is observed. When set to {@code false} the carrier is
      * expected to have implemented their own notification mechanism.
+     * @hide
      */
     public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL =
             "data_rapid_notification_bool";