Merge "Add device and carrier flags for video calling fallback"
diff --git a/api/test-current.txt b/api/test-current.txt
index 6a70957..201d9b3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -47159,6 +47159,7 @@
     method public void setColorMode(int);
     method public final void setTitle(java.lang.CharSequence);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int ALPHA_CHANGED = 128; // 0x80
     field public static final int ANIMATION_CHANGED = 16; // 0x10
     field public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
@@ -47260,6 +47261,7 @@
     field public static final deprecated int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
     field public static final deprecated int TYPE_TOAST = 2005; // 0x7d5
     field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
+    field public java.lang.CharSequence accessibilityTitle;
     field public float alpha;
     field public float buttonBrightness;
     field public float dimAmount;
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 5fedc9e..607e6e0 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -33,17 +33,24 @@
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
 
+#include <system/graphics.h>
+
 // TODO: Fix Skia.
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #include <SkImageEncoder.h>
 #include <SkData.h>
+#include <SkColorSpace.h>
 #pragma GCC diagnostic pop
 
 using namespace android;
 
 static uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain;
 
+#define COLORSPACE_UNKNOWN    0
+#define COLORSPACE_SRGB       1
+#define COLORSPACE_DISPLAY_P3 2
+
 static void usage(const char* pname)
 {
     fprintf(stderr,
@@ -67,6 +74,31 @@
     }
 }
 
+static sk_sp<SkColorSpace> dataSpaceToColorSpace(android_dataspace d)
+{
+    switch (d) {
+        case HAL_DATASPACE_V0_SRGB:
+            return SkColorSpace::MakeSRGB();
+        case HAL_DATASPACE_DISPLAY_P3:
+            return SkColorSpace::MakeRGB(
+                    SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
+        default:
+            return nullptr;
+    }
+}
+
+static uint32_t dataSpaceToInt(android_dataspace d)
+{
+    switch (d) {
+        case HAL_DATASPACE_V0_SRGB:
+            return COLORSPACE_SRGB;
+        case HAL_DATASPACE_DISPLAY_P3:
+            return COLORSPACE_DISPLAY_P3;
+        default:
+            return COLORSPACE_UNKNOWN;
+    }
+}
+
 static status_t notifyMediaScanner(const char* fileName) {
     String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
     String8 fileUrl("\"");
@@ -139,6 +171,7 @@
 
     void const* base = NULL;
     uint32_t w, s, h, f;
+    android_dataspace d;
     size_t size = 0;
 
     // Maps orientations from DisplayInfo to ISurfaceComposer
@@ -177,13 +210,15 @@
         h = screenshot.getHeight();
         s = screenshot.getStride();
         f = screenshot.getFormat();
+        d = screenshot.getDataSpace();
         size = screenshot.getSize();
     }
 
     if (base != NULL) {
         if (png) {
             const SkImageInfo info =
-                SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType);
+                SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
+                    dataSpaceToColorSpace(d));
             SkPixmap pixmap(info, base, s * bytesPerPixel(f));
             struct FDWStream final : public SkWStream {
               size_t fBytesWritten = 0;
@@ -200,9 +235,11 @@
                 notifyMediaScanner(fn);
             }
         } else {
+            uint32_t c = dataSpaceToInt(d);
             write(fd, &w, 4);
             write(fd, &h, 4);
             write(fd, &f, 4);
+            write(fd, &c, 4);
             size_t Bpp = bytesPerPixel(f);
             for (size_t y=0 ; y<h ; y++) {
                 write(fd, base, w*Bpp);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9c2e11d..dec5f4f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -301,6 +301,19 @@
     public static final int START_INTENT_NOT_RESOLVED = FIRST_START_FATAL_ERROR_CODE + 9;
 
     /**
+     * Result for IActivityManager.startAssistantActivity: active session is currently hidden.
+     * @hide
+     */
+    public static final int START_ASSISTANT_HIDDEN_SESSION = FIRST_START_FATAL_ERROR_CODE + 10;
+
+    /**
+     * Result for IActivityManager.startAssistantActivity: active session does not match
+     * the requesting token.
+     * @hide
+     */
+    public static final int START_ASSISTANT_NOT_ACTIVE_SESSION = FIRST_START_FATAL_ERROR_CODE + 11;
+
+    /**
      * Result for IActivityManaqer.startActivity: the activity was started
      * successfully as normal.
      * @hide
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index dfa1c57..df55080 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -29,8 +29,8 @@
 import android.content.ContentProvider;
 import android.content.Context;
 import android.content.IContentProvider;
-import android.content.Intent;
 import android.content.IIntentReceiver;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
@@ -91,6 +91,7 @@
 import android.provider.Downloads;
 import android.provider.FontsContract;
 import android.provider.Settings;
+import android.renderscript.RenderScriptCacheDir;
 import android.security.NetworkSecurityPolicy;
 import android.security.net.config.NetworkSecurityConfigProvider;
 import android.util.AndroidRuntimeException;
@@ -114,7 +115,6 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
-import android.renderscript.RenderScriptCacheDir;
 import android.webkit.WebView;
 
 import com.android.internal.annotations.GuardedBy;
@@ -128,8 +128,21 @@
 import com.android.internal.util.FastPrintWriter;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.android.org.conscrypt.TrustedCertificateStore;
+
+import dalvik.system.BaseDexClassLoader;
+import dalvik.system.CloseGuard;
+import dalvik.system.VMDebug;
+import dalvik.system.VMRuntime;
+
 import com.google.android.collect.Lists;
 
+import libcore.io.DropBox;
+import libcore.io.EventLogger;
+import libcore.io.IoUtils;
+import libcore.net.event.NetworkEventDispatcher;
+
+import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
@@ -146,16 +159,6 @@
 import java.util.Objects;
 import java.util.TimeZone;
 
-import libcore.io.DropBox;
-import libcore.io.EventLogger;
-import libcore.io.IoUtils;
-import libcore.net.event.NetworkEventDispatcher;
-import dalvik.system.BaseDexClassLoader;
-import dalvik.system.CloseGuard;
-import dalvik.system.VMDebug;
-import dalvik.system.VMRuntime;
-import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
-
 final class RemoteServiceException extends AndroidRuntimeException {
     public RemoteServiceException(String msg) {
         super(msg);
@@ -2887,6 +2890,9 @@
             TAG, "Handling launch of " + r);
 
         // Initialize before creating the activity
+        if (!ThreadedRenderer.sRendererDisabled) {
+            GraphicsEnvironment.earlyInitEGL();
+        }
         WindowManagerGlobal.initialize();
 
         Activity a = performLaunchActivity(r, customIntent);
@@ -5372,26 +5378,45 @@
         WindowManagerGlobal.getInstance().trimMemory(level);
     }
 
-    private void setupGraphicsSupport(Context context, File cacheDir) {
-        if (Process.isIsolated()) {
-            // Isolated processes aren't going to do UI.
-            return;
-        }
+    private void setupGraphicsSupport(Context context) {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setupGraphicsSupport");
-        try {
-            int uid = Process.myUid();
-            String[] packages = getPackageManager().getPackagesForUid(uid);
 
-            if (packages != null) {
-                ThreadedRenderer.setupDiskCache(cacheDir);
-                RenderScriptCacheDir.setupDiskCache(cacheDir);
-                GraphicsEnvironment.setupGraphicsEnvironment(context);
+        // The system package doesn't have real data directories, so don't set up cache paths.
+        if (!"android".equals(context.getPackageName())) {
+            // This cache location probably points at credential-encrypted
+            // storage which may not be accessible yet; assign it anyway instead
+            // of pointing at device-encrypted storage.
+            final File cacheDir = context.getCacheDir();
+            if (cacheDir != null) {
+                // Provide a usable directory for temporary files
+                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+            } else {
+                Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
+                        + "due to missing cache directory");
             }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+            // Setup a location to store generated/compiled graphics code.
+            final Context deviceContext = context.createDeviceProtectedStorageContext();
+            final File codeCacheDir = deviceContext.getCodeCacheDir();
+            if (codeCacheDir != null) {
+                try {
+                    int uid = Process.myUid();
+                    String[] packages = getPackageManager().getPackagesForUid(uid);
+                    if (packages != null) {
+                        ThreadedRenderer.setupDiskCache(cacheDir);
+                        RenderScriptCacheDir.setupDiskCache(cacheDir);
+                    }
+                } catch (RemoteException e) {
+                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+                    throw e.rethrowFromSystemServer();
+                }
+            } else {
+                Log.w(TAG, "Unable to use shader/script cache: missing code-cache directory");
+            }
         }
+
+        GraphicsEnvironment.chooseDriver(context);
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
     private void updateDefaultDensity() {
@@ -5664,27 +5689,8 @@
         updateLocaleListFromAppContext(appContext,
                 mResourcesManager.getConfiguration().getLocales());
 
-        if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
-            // This cache location probably points at credential-encrypted
-            // storage which may not be accessible yet; assign it anyway instead
-            // of pointing at device-encrypted storage.
-            final File cacheDir = appContext.getCacheDir();
-            if (cacheDir != null) {
-                // Provide a usable directory for temporary files
-                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
-            } else {
-                Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
-                        + "due to missing cache directory");
-            }
-
-            // Setup a location to store generated/compiled graphics code.
-            final Context deviceContext = appContext.createDeviceProtectedStorageContext();
-            final File codeCacheDir = deviceContext.getCodeCacheDir();
-            if (codeCacheDir != null) {
-                setupGraphicsSupport(appContext, codeCacheDir);
-            } else {
-                Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
-            }
+        if (!Process.isIsolated()) {
+            setupGraphicsSupport(appContext);
         }
 
         // If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 84efcee..467fc95 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1953,6 +1953,12 @@
             case ActivityManager.START_VOICE_HIDDEN_SESSION:
                 throw new IllegalStateException(
                         "Cannot start voice activity on a hidden session");
+            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
+                throw new IllegalStateException(
+                        "Session calling startAssistantActivity does not match active session");
+            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
+                throw new IllegalStateException(
+                        "Cannot start assistant activity on a hidden session");
             case ActivityManager.START_CANCELED:
                 throw new AndroidRuntimeException("Activity could not be started for "
                         + intent);
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index f9eaba9..07c6055 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -35,23 +35,12 @@
     private static final String TAG = "GraphicsEnvironment";
     private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
 
-    public static void setupGraphicsEnvironment(Context context) {
-        chooseDriver(context);
-
-        // Now that we've figured out which driver to use for this process, load and initialize it.
-        // This can take multiple frame periods, and it would otherwise happen as part of the first
-        // frame, increasing first-frame latency. Starting it here, as a low-priority background
-        // thread, means that it's usually done long before we start drawing the first frame,
-        // without significantly disrupting other activity launch work.
-        Thread eglInitThread = new Thread(
-                () -> {
-                    EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
-                },
-                "EGL Init");
-        eglInitThread.start();
-    }
-
-    private static void chooseDriver(Context context) {
+    /**
+     * Choose whether the current process should use the builtin or an updated driver.
+     *
+     * @hide
+     */
+    public static void chooseDriver(Context context) {
         String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
         if (driverPackageName == null || driverPackageName.isEmpty()) {
             return;
@@ -101,6 +90,27 @@
         setDriverPath(paths);
     }
 
+    /**
+     * Start a background thread to initialize EGL.
+     *
+     * Initializing EGL involves loading and initializing the graphics driver. Some drivers take
+     * several 10s of milliseconds to do this, so doing it on-demand when an app tries to render
+     * its first frame adds directly to user-visible app launch latency. By starting it earlier
+     * on a separate thread, it can usually be finished well before the UI is ready to be drawn.
+     *
+     * Should only be called after chooseDriver().
+     *
+     * @hide
+     */
+    public static void earlyInitEGL() {
+        Thread eglInitThread = new Thread(
+                () -> {
+                    EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+                },
+                "EGL Init");
+        eglInitThread.start();
+    }
+
     private static String chooseAbi(ApplicationInfo ai) {
         String isa = VMRuntime.getCurrentInstructionSet();
         if (ai.primaryCpuAbi != null &&
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 31b2dcc..d1ebc6e 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -318,6 +318,17 @@
     }
 
     /**
+     * The ID passed to setGroup(), or the override, or null.
+     * @hide
+     */
+    public String getGroup() {
+        if (overrideGroupKey != null) {
+            return overrideGroupKey;
+        }
+        return getNotification().getGroup();
+    }
+
+    /**
      * Sets the override group key.
      */
     public void setOverrideGroupKey(String overrideGroupKey) {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index a2a129d..625dd9e 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -235,6 +235,8 @@
 
         @Override
         public void hide() {
+            // Remove any pending messages to show the session
+            mHandlerCaller.removeMessages(MSG_SHOW);
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_HIDE));
         }
 
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index da81efc..aacd687 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -358,7 +358,6 @@
     private long mNativeProxy;
     private boolean mInitialized = false;
     private RenderNode mRootNode;
-    private Choreographer mChoreographer;
     private boolean mRootNodeNeedsUpdate;
 
     private boolean mEnabled;
@@ -425,8 +424,6 @@
     /**
      * Indicates whether threaded rendering is currently requested but not
      * necessarily enabled yet.
-     *
-     * @return True to request threaded rendering, false otherwise.
      */
     void setRequested(boolean requested) {
         mRequested = requested;
@@ -597,6 +594,13 @@
     }
 
     /**
+     * Enable/disable wide gamut rendering on this renderer.
+     */
+    void setWideGamut(boolean wideGamut) {
+        nSetWideGamut(mNativeProxy, wideGamut);
+    }
+
+    /**
      * Gets the current width of the surface. This is the width that the surface
      * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
      *
@@ -933,11 +937,11 @@
             if (mInitialized) return;
             mInitialized = true;
             mAppContext = context.getApplicationContext();
-            initSched(context, renderProxy);
+            initSched(renderProxy);
             initGraphicsStats();
         }
 
-        private void initSched(Context context, long renderProxy) {
+        private void initSched(long renderProxy) {
             try {
                 int tid = nGetRenderThreadTid(renderProxy);
                 ActivityManager.getService().setRenderThread(tid);
@@ -1007,6 +1011,7 @@
     private static native void nSetLightCenter(long nativeProxy,
             float lightX, float lightY, float lightZ);
     private static native void nSetOpaque(long nativeProxy, boolean opaque);
+    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
     private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
     private static native void nDestroy(long nativeProxy, long rootRenderNode);
     private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 84baeb7..8105d24 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10026,12 +10026,20 @@
                 // Going from one cluster to another, so save last-focused.
                 // This covers cluster jumps because they are always FOCUS_DOWN
                 oldFocus.setFocusedInCluster(oldCluster);
+                if (!(oldFocus.mParent instanceof ViewGroup)) {
+                    return;
+                }
                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
                     // This is a result of ordered navigation so consider navigation through
                     // the previous cluster "complete" and clear its last-focused memory.
-                    if (oldFocus.mParent instanceof ViewGroup) {
-                        ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
-                    }
+                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
+                } else if (oldFocus instanceof ViewGroup
+                        && ((ViewGroup) oldFocus).getDescendantFocusability()
+                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
+                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
+                    // This means oldFocus is not focusable since it obviously has a focusable
+                    // child (this). Don't restore focus to it in the future.
+                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
                 }
             }
         }
@@ -13088,7 +13096,7 @@
                 // about in case nothing has focus.  even if this specific view
                 // isn't focusable, it may contain something that is, so let
                 // the root view try to give this focus if nothing else does.
-                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
+                if ((mParent != null)) {
                     mParent.focusableViewAvailable(this);
                 }
             }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c5d4ed2..10de583 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -833,8 +833,9 @@
     public void focusableViewAvailable(View v) {
         if (mParent != null
                 // shortcut: don't report a new focusable view if we block our descendants from
-                // getting focus
+                // getting focus or if we're not visible
                 && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
+                && ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
                 && (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())
                 // shortcut: don't report a new focusable view if we already are focused
                 // (and we don't prefer our descendants)
@@ -1159,18 +1160,25 @@
         // Determine whether we have a focused descendant.
         final int descendantFocusability = getDescendantFocusability();
         if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
-            final int count = mChildrenCount;
-            final View[] children = mChildren;
+            return hasFocusableChild(dispatchExplicit);
+        }
 
-            for (int i = 0; i < count; i++) {
-                final View child = children[i];
+        return false;
+    }
 
-                // In case the subclass has overridden has[Explicit]Focusable, dispatch
-                // to the expected one for each child even though we share logic here.
-                if ((dispatchExplicit && child.hasExplicitFocusable())
-                        || (!dispatchExplicit && child.hasFocusable())) {
-                    return true;
-                }
+    boolean hasFocusableChild(boolean dispatchExplicit) {
+        // Determine whether we have a focusable descendant.
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+
+        for (int i = 0; i < count; i++) {
+            final View child = children[i];
+
+            // In case the subclass has overridden has[Explicit]Focusable, dispatch
+            // to the expected one for each child even though we share logic here.
+            if ((dispatchExplicit && child.hasExplicitFocusable())
+                    || (!dispatchExplicit && child.hasFocusable())) {
+                return true;
             }
         }
 
@@ -3230,7 +3238,7 @@
             // will refer to a view not-in a cluster.
             return restoreFocusInCluster(View.FOCUS_DOWN);
         }
-        if (isKeyboardNavigationCluster()) {
+        if (isKeyboardNavigationCluster() || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
         int descendentFocusability = getDescendantFocusability();
@@ -3248,7 +3256,7 @@
                 return true;
             }
         }
-        if (descendentFocusability == FOCUS_AFTER_DESCENDANTS) {
+        if (descendentFocusability == FOCUS_AFTER_DESCENDANTS && !hasFocusableChild(false)) {
             return super.requestFocus(FOCUS_DOWN, null);
         }
         return false;
@@ -4915,7 +4923,8 @@
             child.mParent = this;
         }
 
-        if (child.hasFocus()) {
+        final boolean childHasFocus = child.hasFocus();
+        if (childHasFocus) {
             requestChildFocus(child, child.findFocus());
         }
 
@@ -4928,6 +4937,9 @@
                 needGlobalAttributesUpdate(true);
             }
             ai.mKeepScreenOn = lastKeepOn;
+            if (!childHasFocus && child.hasFocusable()) {
+                focusableViewAvailable(child);
+            }
         }
 
         if (child.isLayoutDirectionInherited()) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3759f9e..9a3d1b9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -35,6 +35,7 @@
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -960,8 +961,12 @@
                 final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
                         || insets.top != 0 || insets.bottom != 0;
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
+                final boolean wideGamut =
+                        attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
+
                 mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
                         attrs.getTitle().toString());
+                mAttachInfo.mThreadedRenderer.setWideGamut(wideGamut);
                 if (mAttachInfo.mThreadedRenderer != null) {
                     mAttachInfo.mHardwareAccelerated =
                             mAttachInfo.mHardwareAccelerationRequested = true;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3f91476..12ff217 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1903,6 +1903,7 @@
          *
          * @hide
          */
+        @TestApi
         public CharSequence accessibilityTitle;
 
         /**
@@ -2089,6 +2090,7 @@
             out.writeInt(needsMenuKey);
             out.writeInt(accessibilityIdOfAnchor);
             TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
+            out.writeInt(mColorMode);
             out.writeLong(hideTimeoutMilliseconds);
         }
 
@@ -2143,6 +2145,7 @@
             needsMenuKey = in.readInt();
             accessibilityIdOfAnchor = in.readInt();
             accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+            mColorMode = in.readInt();
             hideTimeoutMilliseconds = in.readLong();
         }
 
@@ -2185,8 +2188,11 @@
         /** {@hide} */
         public static final int ACCESSIBILITY_ANCHOR_CHANGED = 1 << 24;
         /** {@hide} */
+        @TestApi
         public static final int ACCESSIBILITY_TITLE_CHANGED = 1 << 25;
         /** {@hide} */
+        public static final int COLOR_MODE_CHANGED = 1 << 26;
+        /** {@hide} */
         public static final int EVERYTHING_CHANGED = 0xffffffff;
 
         // internal buffer to backup/restore parameters under compatibility mode.
@@ -2364,6 +2370,11 @@
                 changes |= ACCESSIBILITY_TITLE_CHANGED;
             }
 
+            if (mColorMode != o.mColorMode) {
+                mColorMode = o.mColorMode;
+                changes |= COLOR_MODE_CHANGED;
+            }
+
             // This can't change, it's only set at window creation time.
             hideTimeoutMilliseconds = o.hideTimeoutMilliseconds;
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index cc14542..ec2b302 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1956,12 +1956,12 @@
      * messages to a certain target origin. See
      * <a href="https://html.spec.whatwg.org/multipage/comms.html#posting-messages">
      * HTML5 spec</a> for how target origin can be used.
+     * <p>
+     * A target origin can be set as a wildcard ("*"). However this is not recommended.
+     * See the page above for security issues.
      *
      * @param message the WebMessage
-     * @param targetOrigin the target origin. This is the origin of the page
-     *          that is intended to receive the message. For best security
-     *          practices, the user should not specify a wildcard (*) when
-     *          specifying the origin.
+     * @param targetOrigin the target origin.
      */
     public void postWebMessage(WebMessage message, Uri targetOrigin) {
         checkThread();
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 82071d7..fcb44af 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1718,20 +1718,17 @@
                     break;
 
                 case KeyEvent.KEYCODE_TAB:
-                    // XXX Sometimes it is useful to be able to TAB through the items in
+                    // TODO: Sometimes it is useful to be able to TAB through the items in
                     //     a GridView sequentially.  Unfortunately this can create an
                     //     asymmetry in TAB navigation order unless the list selection
                     //     always reverts to the top or bottom when receiving TAB focus from
-                    //     another widget.  Leaving this behavior disabled for now but
-                    //     perhaps it should be configurable (and more comprehensive).
-                    if (false) {
-                        if (event.hasNoModifiers()) {
-                            handled = resurrectSelectionIfNeeded()
-                                    || sequenceScroll(FOCUS_FORWARD);
-                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
-                            handled = resurrectSelectionIfNeeded()
-                                    || sequenceScroll(FOCUS_BACKWARD);
-                        }
+                    //     another widget.
+                    if (event.hasNoModifiers()) {
+                        handled = resurrectSelectionIfNeeded()
+                                || sequenceScroll(FOCUS_FORWARD);
+                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                        handled = resurrectSelectionIfNeeded()
+                                || sequenceScroll(FOCUS_BACKWARD);
                     }
                     break;
             }
@@ -1991,7 +1988,7 @@
 
         if (!mStackFromBottom) {
             rowStart = childIndex - (childIndex % mNumColumns);
-            rowEnd = Math.max(rowStart + mNumColumns - 1, count);
+            rowEnd = Math.min(rowStart + mNumColumns - 1, count);
         } else {
             rowEnd = count - 1 - (invertedIndex - (invertedIndex % mNumColumns));
             rowStart = Math.max(0, rowEnd - mNumColumns + 1);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index de56092..6b328ea 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1587,7 +1587,7 @@
         if (textColorHighlight != 0) {
             setHighlightColor(textColorHighlight);
         }
-        setRawTextSize(textSize);
+        setRawTextSize(textSize, true /* shouldRequestLayout */);
         setElegantTextHeight(elegant);
         setLetterSpacing(letterSpacing);
         setFontFeatureSettings(fontFeatureSettings);
@@ -1757,7 +1757,10 @@
                             autoSizeMinTextSizeInPx,
                             autoSizeMaxTextSizeInPx,
                             DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX);
-                    setupAutoSizeText();
+                    if (setupAutoSizeText()) {
+                        autoSizeText();
+                        invalidate();
+                    }
                     break;
                 default:
                     throw new IllegalArgumentException(
@@ -1807,7 +1810,11 @@
             validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx,
                     autoSizeMaxTextSizeInPx,
                     autoSizeStepGranularityInPx);
-            setupAutoSizeText();
+
+            if (setupAutoSizeText()) {
+                autoSizeText();
+                invalidate();
+            }
         }
     }
 
@@ -1856,7 +1863,11 @@
             } else {
                 mHasPresetAutoSizeValues = false;
             }
-            setupAutoSizeText();
+
+            if (setupAutoSizeText()) {
+                autoSizeText();
+                invalidate();
+            }
         }
     }
 
@@ -2014,20 +2025,19 @@
             : uniqueValidSizes.toArray();
     }
 
-    private void setupAutoSizeText() {
+    private boolean setupAutoSizeText() {
         if (supportsAutoSizeText() && mAutoSizeTextType == AUTO_SIZE_TEXT_TYPE_UNIFORM) {
             // Calculate the sizes set based on minimum size, maximum size and step size if we do
             // not have a predefined set of sizes or if the current sizes array is empty.
             if (!mHasPresetAutoSizeValues || mAutoSizeTextSizesInPx.length == 0) {
-                // Calculate sizes to choose from based on the current auto-size configuration.
-                int autoSizeValuesLength = (int) Math.ceil(
-                        (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
-                                / mAutoSizeStepGranularityInPx);
-                // Also reserve a slot for the max size if it fits.
-                if ((mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
-                        % mAutoSizeStepGranularityInPx == 0) {
+                int autoSizeValuesLength = 1;
+                float currentSize = Math.round(mAutoSizeMinTextSizeInPx);
+                while (Math.round(currentSize + mAutoSizeStepGranularityInPx)
+                        <= Math.round(mAutoSizeMaxTextSizeInPx)) {
                     autoSizeValuesLength++;
+                    currentSize += mAutoSizeStepGranularityInPx;
                 }
+
                 int[] autoSizeTextSizesInPx = new int[autoSizeValuesLength];
                 float sizeToAdd = mAutoSizeMinTextSizeInPx;
                 for (int i = 0; i < autoSizeValuesLength; i++) {
@@ -2038,8 +2048,11 @@
             }
 
             mNeedsAutoSizeText = true;
-            autoSizeText();
+        } else {
+            mNeedsAutoSizeText = false;
         }
+
+        return mNeedsAutoSizeText;
     }
 
     private int[] parseDimensionArray(TypedArray dimens) {
@@ -3387,7 +3400,7 @@
 
         final int textSize = ta.getDimensionPixelSize(R.styleable.TextAppearance_textSize, 0);
         if (textSize != 0) {
-            setRawTextSize(textSize);
+            setRawTextSize(textSize, true /* shouldRequestLayout */);
         }
 
         final ColorStateList textColorHint = ta.getColorStateList(
@@ -3612,11 +3625,11 @@
      */
     public void setTextSize(int unit, float size) {
         if (!isAutoSizeEnabled()) {
-            setTextSizeInternal(unit, size);
+            setTextSizeInternal(unit, size, true /* shouldRequestLayout */);
         }
     }
 
-    private void setTextSizeInternal(int unit, float size) {
+    private void setTextSizeInternal(int unit, float size, boolean shouldRequestLayout) {
         Context c = getContext();
         Resources r;
 
@@ -3626,15 +3639,15 @@
             r = c.getResources();
         }
 
-        setRawTextSize(TypedValue.applyDimension(
-                unit, size, r.getDisplayMetrics()));
+        setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),
+                shouldRequestLayout);
     }
 
-    private void setRawTextSize(float size) {
+    private void setRawTextSize(float size, boolean shouldRequestLayout) {
         if (size != mTextPaint.getTextSize()) {
             mTextPaint.setTextSize(size);
 
-            if (mLayout != null) {
+            if (shouldRequestLayout && mLayout != null) {
                 // Do not auto-size right after setting the text size.
                 mNeedsAutoSizeText = false;
                 nullLayouts();
@@ -8257,23 +8270,44 @@
      * Automatically computes and sets the text size.
      */
     private void autoSizeText() {
-        if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0) return;
-        final int maxWidth = getWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
-        final int maxHeight = getHeight() - getExtendedPaddingBottom() - getExtendedPaddingTop();
-
-        if (maxWidth <= 0 || maxHeight <= 0) {
+        if (!isAutoSizeEnabled()) {
             return;
         }
 
-        synchronized (TEMP_RECTF) {
-            TEMP_RECTF.setEmpty();
-            TEMP_RECTF.right = maxWidth;
-            TEMP_RECTF.bottom = maxHeight;
-            final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
-            if (optimalTextSize != getTextSize()) {
-                setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
+        if (mNeedsAutoSizeText) {
+            if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0) {
+                return;
+            }
+
+            final int availableWidth = mHorizontallyScrolling
+                    ? VERY_WIDE
+                    : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
+            final int availableHeight = getMeasuredHeight() - getExtendedPaddingBottom()
+                    - getExtendedPaddingTop();
+
+            if (availableWidth <= 0 || availableHeight <= 0) {
+                return;
+            }
+
+            synchronized (TEMP_RECTF) {
+                TEMP_RECTF.setEmpty();
+                TEMP_RECTF.right = availableWidth;
+                TEMP_RECTF.bottom = availableHeight;
+                final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
+
+                if (optimalTextSize != getTextSize()) {
+                    setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize,
+                            false /* shouldRequestLayout */);
+
+                    makeNewLayout(availableWidth, 0 /* hintWidth */, UNKNOWN_BORING, UNKNOWN_BORING,
+                            mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
+                            false /* bringIntoView */);
+                }
             }
         }
+        // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
+        // after the next layout pass should set this to false.
+        mNeedsAutoSizeText = true;
     }
 
     /**
@@ -8315,11 +8349,8 @@
         mTempTextPaint.set(getPaint());
         mTempTextPaint.setTextSize(suggestedSizeInPx);
 
-        final int availableWidth = mHorizontallyScrolling
-                ? VERY_WIDE
-                : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
         final StaticLayout.Builder layoutBuilder = StaticLayout.Builder.obtain(
-                text, 0, text.length(),  mTempTextPaint, availableWidth);
+                text, 0, text.length(),  mTempTextPaint, Math.round(availableSpace.right));
 
         layoutBuilder.setAlignment(getLayoutAlignment())
                 .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
@@ -8469,6 +8500,7 @@
                 // In a fixed-height view, so use our new text layout.
                 if (mLayoutParams.height != LayoutParams.WRAP_CONTENT
                         && mLayoutParams.height != LayoutParams.MATCH_PARENT) {
+                    autoSizeText();
                     invalidate();
                     return;
                 }
@@ -8477,6 +8509,7 @@
                 // so use our new text layout.
                 if (mLayout.getHeight() == oldht
                         && (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
+                    autoSizeText();
                     invalidate();
                     return;
                 }
@@ -8503,16 +8536,8 @@
             mDeferScroll = -1;
             bringPointIntoView(Math.min(curs, mText.length()));
         }
-
-        if (isAutoSizeEnabled()) {
-            if (mNeedsAutoSizeText) {
-                // Call auto-size after the width and height have been calculated.
-                autoSizeText();
-            }
-            // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
-            // after the next layout round should set this to false.
-            mNeedsAutoSizeText = true;
-        }
+        // Call auto-size after the width and height have been calculated.
+        autoSizeText();
     }
 
     private boolean isShowingHint() {
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
index d19f1ec..bb54085 100644
--- a/core/java/com/android/internal/app/NightDisplayController.java
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -109,17 +109,39 @@
     }
 
     /**
-     * Sets whether Night display should be activated.
+     * Sets whether Night display should be activated. This also sets the last activated time.
      *
      * @param activated {@code true} if Night display should be activated
      * @return {@code true} if the activated value was set successfully
      */
     public boolean setActivated(boolean activated) {
+        if (isActivated() != activated) {
+            Secure.putLongForUser(mContext.getContentResolver(),
+                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
+                    mUserId);
+        }
         return Secure.putIntForUser(mContext.getContentResolver(),
                 Secure.NIGHT_DISPLAY_ACTIVATED, activated ? 1 : 0, mUserId);
     }
 
     /**
+     * Returns the time when Night display's activation state last changed, or {@code null} if it
+     * has never been changed.
+     */
+    public Calendar getLastActivatedTime() {
+        final ContentResolver cr = mContext.getContentResolver();
+        final long lastActivatedTimeMillis = Secure.getLongForUser(
+                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mUserId);
+        if (lastActivatedTimeMillis < 0) {
+            return null;
+        }
+
+        final Calendar lastActivatedTime = Calendar.getInstance();
+        lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
+        return lastActivatedTime;
+    }
+
+    /**
      * Returns the current auto mode value controlling when Night display will be automatically
      * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
      * {@link #AUTO_MODE_TWILIGHT}.
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index 568c883..9fbc4a8 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -53,10 +53,21 @@
 
     private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();
 
+    // We check the existence of proc file a few times (just in case it is not ready yet when we
+    // start reading) and if it is not available, we simply ignore further read requests.
+    private static final int TOTAL_READ_ERROR_COUNT = 5;
+    private int mReadErrorCounter;
+    private boolean mProcFileAvailable;
+
     public void readDelta(@Nullable Callback callback) {
+        if (!mProcFileAvailable && mReadErrorCounter >= TOTAL_READ_ERROR_COUNT) {
+            return;
+        }
         try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
             readDelta(reader, callback);
+            mProcFileAvailable = true;
         } catch (IOException e) {
+            mReadErrorCounter++;
             Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
         }
     }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index a019ea1..3f35c91 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -93,4 +93,10 @@
      * @param fadeoutDuration the duration of the exit animation, in milliseconds
      */
     void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+
+    /**
+     * Notifies the Keyguard that the power key was pressed while locked and launched Home rather
+     * than putting the device to sleep or waking up.
+     */
+    void onShortPowerPressedGoHome();
 }
diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java
index ebbbdbb..d834e63 100644
--- a/core/java/com/android/internal/view/TooltipPopup.java
+++ b/core/java/com/android/internal/view/TooltipPopup.java
@@ -25,6 +25,7 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.widget.PopupWindow;
 import android.widget.TextView;
 
 public class TooltipPopup {
@@ -32,6 +33,7 @@
 
     private final Context mContext;
 
+    private final PopupWindow mPopupWindow;
     private final View mContentView;
     private final TextView mMessageView;
 
@@ -43,6 +45,8 @@
     public TooltipPopup(Context context) {
         mContext = context;
 
+        mPopupWindow = new PopupWindow(context);
+        mPopupWindow.setBackgroundDrawable(null);
         mContentView = LayoutInflater.from(mContext).inflate(
                 com.android.internal.R.layout.tooltip, null);
         mMessageView = (TextView) mContentView.findViewById(
@@ -70,17 +74,16 @@
 
         computePosition(anchorView, anchorX, anchorY, fromTouch, mLayoutParams);
 
-        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-        wm.addView(mContentView, mLayoutParams);
+        mPopupWindow.setContentView(mContentView);
+        mPopupWindow.showAtLocation(
+            anchorView, mLayoutParams.gravity, mLayoutParams.x, mLayoutParams.y);
     }
 
     public void hide() {
         if (!isShowing()) {
             return;
         }
-
-        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-        wm.removeView(mContentView);
+        mPopupWindow.dismiss();
     }
 
     public View getContentView() {
@@ -88,7 +91,7 @@
     }
 
     public boolean isShowing() {
-        return mContentView.getParent() != null;
+        return mPopupWindow.isShowing();
     }
 
     public void updateContent(CharSequence tooltipText) {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d476ea0..e3b9178 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1714,6 +1714,10 @@
         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1L, UserHandle.USER_SYSTEM);
     }
 
+    public void disableSyntheticPassword() {
+        setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0L, UserHandle.USER_SYSTEM);
+    }
+
     public boolean isSyntheticPasswordEnabled() {
         return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0;
     }
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 5f803da..f04abec 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -63,14 +63,17 @@
 static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
         jint tileModeX, jint tileModeY) {
     const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
-    SkBitmap bitmap;
+    sk_sp<SkImage> image;
     if (jbitmap) {
         // Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
         // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
-        android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
+        image = android::bitmap::toBitmap(env, jbitmap).makeImage();
     }
 
-    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!image.get()) {
+        SkBitmap bitmap;
+        image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    }
     sk_sp<SkShader> baseShader = image->makeShader(
             (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY);
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 497f00c..97aa562 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -221,11 +221,20 @@
             return NULL;
         }
     }
+
+    sk_sp<SkColorSpace> colorSpace;
+    if (screenshot->getDataSpace() == HAL_DATASPACE_DISPLAY_P3) {
+        colorSpace = SkColorSpace::MakeRGB(
+                SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
+    } else {
+        colorSpace = SkColorSpace::MakeSRGB();
+    }
+
     SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
                                                    screenshot->getHeight(),
                                                    colorType,
                                                    alphaType,
-                                                   GraphicsJNI::defaultColorSpace());
+                                                   colorSpace);
 
     const size_t rowBytes =
             screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 4c530d7..2657140 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -208,8 +208,15 @@
 
     void detachAnimators() {
         // Remove animators from the list and post a delayed message in future to end the animator
+        // For infinite animators, remove the listener so we no longer hold a global ref to the AVD
+        // java object, and therefore the AVD objects in both native and Java can be properly
+        // released.
         for (auto& anim : mRunningVDAnimators) {
             detachVectorDrawableAnimator(anim.get());
+            anim->clearOneShotListener();
+        }
+        for (auto& anim : mPausedVDAnimators) {
+            anim->clearOneShotListener();
         }
         mRunningVDAnimators.clear();
         mPausedVDAnimators.clear();
@@ -674,6 +681,12 @@
     proxy->setOpaque(opaque);
 }
 
+static void android_view_ThreadedRenderer_setWideGamut(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jboolean wideGamut) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->setWideGamut(wideGamut);
+}
+
 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
@@ -865,7 +878,8 @@
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> rawConsumer;
     BufferQueue::createBufferQueue(&producer, &rawConsumer);
-    rawConsumer->setMaxBufferCount(1);
+    // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2
+    rawConsumer->setMaxBufferCount(2);
     sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer,
             GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
     consumer->setDefaultBufferSize(width, height);
@@ -974,6 +988,7 @@
     { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
     { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
+    { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
     { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
     { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 76310b8..9c4d489 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3228,6 +3228,9 @@
 
     <!-- Alert windows notification strings -->
     <skip />
+    <!-- Name of notification channel group the system post notification to inform the use about apps
+         that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
+    <string name="alert_windows_notification_channel_group_name">Display over other apps</string>
     <!-- Name of notification channel the system post notification to inform the use about apps
          that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
     <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ca3baa6..6554d44 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2965,6 +2965,7 @@
   <java-symbol type="drawable" name="resolver_icon_placeholder" />
 
   <!-- Alert windows notification -->
+  <java-symbol type="string" name="alert_windows_notification_channel_group_name" />
   <java-symbol type="string" name="alert_windows_notification_channel_name" />
   <java-symbol type="string" name="alert_windows_notification_title" />
   <java-symbol type="string" name="alert_windows_notification_message" />
diff --git a/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java b/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
index dd07a08..3ddeef0 100644
--- a/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
+++ b/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
@@ -16,16 +16,15 @@
 
 package android.widget.touchmode;
 
-import android.widget.layout.linear.LLEditTextThenButton;
-import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
 import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterClick;
+import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
 
 import android.test.ActivityInstrumentationTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.layout.linear.LLEditTextThenButton;
 
 /**
  * Some views, like edit texts, can keep and gain focus even when in touch mode.
@@ -64,7 +63,8 @@
     @LargeTest
     public void testClickEditTextGivesItFocus() {
         // go down to button
-        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        getActivity().runOnUiThread(() -> mButton.requestFocus());
+        getInstrumentation().waitForIdleSync();
         assertTrue("button should have focus", mButton.isFocused());
 
         assertInTouchModeAfterClick(this, mEditText);
@@ -77,11 +77,12 @@
     // isn't focusable in touch mode.
     @LargeTest
     public void testEnterTouchModeGivesFocusBackToFocusableInTouchMode() {
-        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        getActivity().runOnUiThread(() -> mButton.requestFocus());
+        getInstrumentation().waitForIdleSync();
 
         assertTrue("button should have focus",
                 mButton.isFocused());
-        
+
         assertInTouchModeAfterClick(this, mButton);
         assertTrue("should be in touch mode", mButton.isInTouchMode());
         assertNull("nothing should have focus", getActivity().getCurrentFocus());
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 8ce7ed0..aa38f31 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -44,6 +44,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -493,7 +494,7 @@
             case TYPE_DATA:
                 return getDataLength() == otherIcon.getDataLength()
                         && getDataOffset() == otherIcon.getDataOffset()
-                        && getDataBytes() == otherIcon.getDataBytes();
+                        && Arrays.equals(getDataBytes(), otherIcon.getDataBytes());
             case TYPE_RESOURCE:
                 return getResId() == otherIcon.getResId()
                         && Objects.equals(getResPackage(), otherIcon.getResPackage());
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index d0f0949..8cc0aa7 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -58,7 +58,9 @@
         "uniform mat4 textureTransform;\n"
         "uniform mediump vec2 textureDimension;\n";
 const char* gVS_Header_Uniforms_HasRoundRectClip =
-        "uniform mat4 roundRectInvTransform;\n";
+        "uniform mat4 roundRectInvTransform;\n"
+        "uniform mediump vec4 roundRectInnerRectLTWH;\n"
+        "uniform mediump float roundRectRadius;\n";
 const char* gVS_Header_Varyings_HasTexture =
         "varying vec2 outTexCoords;\n";
 const char* gVS_Header_Varyings_HasColors =
@@ -81,7 +83,7 @@
         "varying highp vec2 sweep;\n",
 };
 const char* gVS_Header_Varyings_HasRoundRectClip =
-        "varying highp vec2 roundRectPos;\n";
+        "varying mediump vec2 roundRectPos;\n";
 const char* gVS_Main =
         "\nvoid main(void) {\n";
 const char* gVS_Main_OutTexCoords =
@@ -113,7 +115,7 @@
         "    alpha = vtxAlpha;\n";
 
 const char* gVS_Main_HasRoundRectClip =
-        "    roundRectPos = (roundRectInvTransform * transformedPosition).xy;\n";
+        "    roundRectPos = ((roundRectInvTransform * transformedPosition).xy / roundRectRadius) - roundRectInnerRectLTWH.xy;\n";
 const char* gVS_Footer =
         "}\n\n";
 
@@ -158,8 +160,8 @@
 };
 
 const char* gFS_Uniforms_HasRoundRectClip =
-        "uniform vec4 roundRectInnerRectLTRB;\n"
-        "uniform float roundRectRadius;\n";
+        "uniform mediump vec4 roundRectInnerRectLTWH;\n"
+        "uniform mediump float roundRectRadius;\n";
 
 const char* gFS_Uniforms_ColorSpaceConversion =
         // TODO: Should we use a 3D LUT to combine the matrix and transfer functions?
@@ -431,15 +433,18 @@
         "    fragColor = blendColors(colorBlend, fragColor);\n"
 };
 
-// Note: LTRB -> xyzw
+// Note: LTWH (left top width height) -> xyzw
+// roundRectPos is now divided by roundRectRadius in vertex shader
+// after we also subtract roundRectInnerRectLTWH.xy from roundRectPos
 const char* gFS_Main_FragColor_HasRoundRectClip =
-        "    mediump vec2 fragToLT = roundRectInnerRectLTRB.xy - roundRectPos;\n"
-        "    mediump vec2 fragFromRB = roundRectPos - roundRectInnerRectLTRB.zw;\n"
+        "    mediump vec2 fragToLT = -roundRectPos;\n"
+        "    mediump vec2 fragFromRB = roundRectPos - roundRectInnerRectLTWH.zw;\n"
 
-        // divide + multiply by 128 to avoid falling out of range in length() function
-        "    mediump vec2 dist = max(max(fragToLT, fragFromRB), vec2(0.0, 0.0)) / 128.0;\n"
-        "    mediump float linearDist = roundRectRadius - (length(dist) * 128.0);\n"
-        "    gl_FragColor *= clamp(linearDist, 0.0, 1.0);\n";
+        // since distance is divided by radius, it's in [0;1] so precision is not an issue
+        // this also lets us clamp(0.0, 1.0) instead of max() which is cheaper on GPUs
+        "    mediump vec2 dist = clamp(max(fragToLT, fragFromRB), 0.0, 1.0);\n"
+        "    mediump float linearDist = clamp(roundRectRadius - (length(dist) * roundRectRadius), 0.0, 1.0);\n"
+        "    gl_FragColor *= linearDist;\n";
 
 const char* gFS_Main_DebugHighlight =
         "    gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n";
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 4e6a7db..6dde005 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -26,16 +26,12 @@
 #include <log/log.h>
 #include <cutils/ashmem.h>
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include <private/gui/ComposerService.h>
 #include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
 
 #include <SkCanvas.h>
+#include <SkImagePriv.h>
 
 namespace android {
 
@@ -89,171 +85,6 @@
     return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes, std::move(ctable)));
 }
 
-#define FENCE_TIMEOUT 2000000000
-
-// TODO: handle SRGB sanely
-static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
-    switch (internalFormat) {
-    case GL_LUMINANCE:
-        return PIXEL_FORMAT_RGBA_8888;
-    case GL_SRGB8_ALPHA8:
-        return PIXEL_FORMAT_RGBA_8888;
-    case GL_RGBA:
-        return PIXEL_FORMAT_RGBA_8888;
-    case GL_RGB:
-        return PIXEL_FORMAT_RGB_565;
-    case GL_RGBA16F:
-        return PIXEL_FORMAT_RGBA_FP16;
-    default:
-        LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
-        return PIXEL_FORMAT_UNKNOWN;
-    }
-}
-
-class AutoEglFence {
-public:
-    AutoEglFence(EGLDisplay display)
-            : mDisplay(display) {
-        fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
-    }
-
-    ~AutoEglFence() {
-        if (fence != EGL_NO_SYNC_KHR) {
-            eglDestroySyncKHR(mDisplay, fence);
-        }
-    }
-
-    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
-private:
-    EGLDisplay mDisplay = EGL_NO_DISPLAY;
-};
-
-class AutoEglImage {
-public:
-    AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
-            : mDisplay(display) {
-        EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
-        image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
-                EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
-    }
-
-    ~AutoEglImage() {
-        if (image != EGL_NO_IMAGE_KHR) {
-            eglDestroyImageKHR(mDisplay, image);
-        }
-    }
-
-    EGLImageKHR image = EGL_NO_IMAGE_KHR;
-private:
-    EGLDisplay mDisplay = EGL_NO_DISPLAY;
-};
-
-class AutoGlTexture {
-public:
-    AutoGlTexture(uirenderer::Caches& caches)
-            : mCaches(caches) {
-        glGenTextures(1, &mTexture);
-        caches.textureState().bindTexture(mTexture);
-    }
-
-    ~AutoGlTexture() {
-        mCaches.textureState().deleteTexture(mTexture);
-    }
-
-private:
-    uirenderer::Caches& mCaches;
-    GLuint mTexture = 0;
-};
-
-static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
-        GraphicBuffer& buffer, GLint format, GLint type) {
-    EGLDisplay display = eglGetCurrentDisplay();
-    LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
-                "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
-                uirenderer::renderthread::EglManager::eglErrorString());
-    // We use an EGLImage to access the content of the GraphicBuffer
-    // The EGL image is later bound to a 2D texture
-    EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer.getNativeBuffer();
-    AutoEglImage autoImage(display, clientBuffer);
-    if (autoImage.image == EGL_NO_IMAGE_KHR) {
-        ALOGW("Could not create EGL image, err =%s",
-                uirenderer::renderthread::EglManager::eglErrorString());
-        return false;
-    }
-    AutoGlTexture glTexture(caches);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
-
-    GL_CHECKPOINT(MODERATE);
-
-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
-            format, type, bitmap.getPixels());
-
-    GL_CHECKPOINT(MODERATE);
-
-    // The fence is used to wait for the texture upload to finish
-    // properly. We cannot rely on glFlush() and glFinish() as
-    // some drivers completely ignore these API calls
-    AutoEglFence autoFence(display);
-    if (autoFence.fence == EGL_NO_SYNC_KHR) {
-        LOG_ALWAYS_FATAL("Could not create sync fence %#x", eglGetError());
-        return false;
-    }
-    // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
-    // pipeline flush (similar to what a glFlush() would do.)
-    EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
-            EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
-    if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
-        LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
-        return false;
-    }
-    return true;
-}
-
-sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(uirenderer::renderthread::RenderThread& renderThread,
-        SkBitmap& skBitmap) {
-    renderThread.eglManager().initialize();
-    uirenderer::Caches& caches = uirenderer::Caches::getInstance();
-
-    const SkImageInfo& info = skBitmap.info();
-    if (info.colorType() == kUnknown_SkColorType || info.colorType() == kAlpha_8_SkColorType) {
-        ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
-        return nullptr;
-    }
-
-    bool needSRGB = uirenderer::transferFunctionCloseToSRGB(skBitmap.info().colorSpace());
-    bool hasLinearBlending = caches.extensions().hasLinearBlending();
-    GLint format, type, internalFormat;
-    uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
-            needSRGB && hasLinearBlending, &internalFormat, &format, &type);
-
-    PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
-    sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
-            GraphicBuffer::USAGE_HW_TEXTURE |
-            GraphicBuffer::USAGE_SW_WRITE_NEVER |
-            GraphicBuffer::USAGE_SW_READ_NEVER,
-            std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
-
-    status_t error = buffer->initCheck();
-    if (error < 0) {
-        ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
-        return nullptr;
-    }
-
-    SkBitmap bitmap;
-    if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
-            hasLinearBlending))) {
-        sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
-        bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
-    } else {
-        bitmap = skBitmap;
-    }
-
-    if (!uploadBitmapToGraphicBuffer(caches, bitmap, *buffer, format, type)) {
-        return nullptr;
-    }
-    return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info()));
-}
-
 sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(SkBitmap& bitmap) {
     return uirenderer::renderthread::RenderProxy::allocateHardwareBitmap(bitmap);
 }
@@ -392,6 +223,12 @@
         , mPixelStorageType(PixelStorageType::Hardware) {
     mPixelStorage.hardware.buffer = buffer;
     buffer->incStrong(buffer);
+    setImmutable(); // HW bitmaps are always immutable
+    if (uirenderer::Properties::isSkiaEnabled()) {
+        // TODO: add color correctness for Skia pipeline - pass null color space for now
+        mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast<AHardwareBuffer*>(buffer),
+                mInfo.alphaType(), nullptr);
+    }
 }
 
 Bitmap::~Bitmap() {
@@ -486,16 +323,6 @@
     outBitmap->setPixelRef(sk_ref_sp(this), 0, 0);
 }
 
-void Bitmap::getSkBitmapForShaders(SkBitmap* outBitmap) {
-    if (isHardware() && uirenderer::Properties::isSkiaEnabled()) {
-        getSkBitmap(outBitmap);
-    } else {
-        outBitmap->setInfo(info(), rowBytes());
-        outBitmap->setPixelRef(sk_ref_sp(this), 0, 0);
-        outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
-    }
-}
-
 void Bitmap::getBounds(SkRect* bounds) const {
     SkASSERT(bounds);
     bounds->set(0, 0, SkIntToScalar(width()), SkIntToScalar(height()));
@@ -508,4 +335,20 @@
     return nullptr;
 }
 
+sk_sp<SkImage> Bitmap::makeImage() {
+    sk_sp<SkImage> image = mImage;
+    if (!image) {
+        SkASSERT(!(isHardware() && uirenderer::Properties::isSkiaEnabled()));
+        SkBitmap skiaBitmap;
+        skiaBitmap.setInfo(info(), rowBytes());
+        skiaBitmap.setPixelRef(sk_ref_sp(this), 0, 0);
+        skiaBitmap.setHasHardwareMipMap(mHasHardwareMipMap);
+        // Note we don't cache in this case, because the raster image holds a pointer to this Bitmap
+        // internally and ~Bitmap won't be invoked.
+        // TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here.
+        image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+    }
+    return image;
+}
+
 } // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 9a76715..364240670 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -18,10 +18,12 @@
 #include <SkBitmap.h>
 #include <SkColorSpace.h>
 #include <SkColorTable.h>
+#include <SkImage.h>
 #include <SkImageInfo.h>
 #include <SkPixelRef.h>
 #include <cutils/compiler.h>
 #include <ui/GraphicBuffer.h>
+#include <SkImage.h>
 
 namespace android {
 
@@ -57,15 +59,13 @@
 
     static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);
 
-    static sk_sp<Bitmap> allocateHardwareBitmap(uirenderer::renderthread::RenderThread&,
-            SkBitmap& bitmap);
-
     Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
             sk_sp<SkColorTable> ctable);
     Bitmap(void* address, void* context, FreeFunc freeFunc,
             const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable);
     Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
             size_t rowBytes, sk_sp<SkColorTable> ctable);
+    Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
 
     int rowBytesAsPixels() const {
         return rowBytes() >> SkColorTypeShiftPerPixel(mInfo.colorType());
@@ -78,10 +78,6 @@
 
     void getSkBitmap(SkBitmap* outBitmap);
 
-    // Ugly hack: in case of hardware bitmaps, it sets nullptr as pixels pointer
-    // so it would crash if anyone tries to render this bitmap.
-    void getSkBitmapForShaders(SkBitmap* outBitmap);
-
     int getAshmemFd() const;
     size_t getAllocationByteCount() const;
 
@@ -105,8 +101,11 @@
     }
 
     GraphicBuffer* graphicBuffer();
+
+    // makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread.
+    // Caching is supported only for HW Bitmaps with skia pipeline.
+    sk_sp<SkImage> makeImage();
 private:
-    Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
     virtual ~Bitmap();
     void* getStorage() const;
 
@@ -135,6 +134,8 @@
             GraphicBuffer* buffer;
         } hardware;
     } mPixelStorage;
+
+    sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline.
 };
 
 } //namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index ae13131..095d32e 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -16,6 +16,7 @@
 
 #include "SkiaOpenGLPipeline.h"
 
+#include "hwui/Bitmap.h"
 #include "DeferredLayerUpdater.h"
 #include "GlLayer.h"
 #include "LayerDrawable.h"
@@ -155,7 +156,8 @@
     }
 }
 
-bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) {
+bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
+        ColorMode colorMode) {
 
     if (mEglSurface != EGL_NO_SURFACE) {
         mEglManager.destroySurface(mEglSurface);
@@ -163,7 +165,8 @@
     }
 
     if (surface) {
-        mEglSurface = mEglManager.createSurface(surface);
+        const bool wideColorGamut = colorMode == ColorMode::WideColorGamut;
+        mEglSurface = mEglManager.createSurface(surface, wideColorGamut);
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
@@ -197,6 +200,186 @@
     }
 }
 
+#define FENCE_TIMEOUT 2000000000
+
+class AutoEglFence {
+public:
+    AutoEglFence(EGLDisplay display)
+            : mDisplay(display) {
+        fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
+    }
+
+    ~AutoEglFence() {
+        if (fence != EGL_NO_SYNC_KHR) {
+            eglDestroySyncKHR(mDisplay, fence);
+        }
+    }
+
+    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
+private:
+    EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+class AutoEglImage {
+public:
+    AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
+            : mDisplay(display) {
+        EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+        image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
+                EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+    }
+
+    ~AutoEglImage() {
+        if (image != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mDisplay, image);
+        }
+    }
+
+    EGLImageKHR image = EGL_NO_IMAGE_KHR;
+private:
+    EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+class AutoSkiaGlTexture {
+public:
+    AutoSkiaGlTexture() {
+        glGenTextures(1, &mTexture);
+        glBindTexture(GL_TEXTURE_2D, mTexture);
+    }
+
+    ~AutoSkiaGlTexture() {
+        glDeleteTextures(1, &mTexture);
+    }
+
+private:
+    GLuint mTexture = 0;
+};
+
+sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
+        SkBitmap& skBitmap) {
+    renderThread.eglManager().initialize();
+
+    sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
+    const SkImageInfo& info = skBitmap.info();
+    PixelFormat pixelFormat;
+    GLint format, type;
+    bool isSupported = false;
+
+    //TODO: add support for linear blending (when ANDROID_ENABLE_LINEAR_BLENDING is defined)
+    switch (info.colorType()) {
+    case kRGBA_8888_SkColorType:
+        isSupported = true;
+    // ARGB_4444 and Index_8 are both upconverted to RGBA_8888
+    case kIndex_8_SkColorType:
+    case kARGB_4444_SkColorType:
+        pixelFormat = PIXEL_FORMAT_RGBA_8888;
+        format = GL_RGBA;
+        type = GL_UNSIGNED_BYTE;
+        break;
+    case kRGBA_F16_SkColorType:
+        isSupported = grContext->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig);
+        if (isSupported) {
+            type = GL_HALF_FLOAT;
+            pixelFormat = PIXEL_FORMAT_RGBA_FP16;
+        } else {
+            type = GL_UNSIGNED_BYTE;
+            pixelFormat = PIXEL_FORMAT_RGBA_8888;
+        }
+        format = GL_RGBA;
+        break;
+    case kRGB_565_SkColorType:
+        isSupported = true;
+        pixelFormat = PIXEL_FORMAT_RGB_565;
+        format = GL_RGB;
+        type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    case kGray_8_SkColorType:
+        isSupported = true;
+        pixelFormat = PIXEL_FORMAT_RGBA_8888;
+        format = GL_LUMINANCE;
+        type = GL_UNSIGNED_BYTE;
+        break;
+    default:
+        ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
+        return nullptr;
+    }
+
+    SkBitmap bitmap;
+    if (isSupported) {
+        bitmap = skBitmap;
+    } else {
+        bitmap.allocPixels(SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType(),
+                nullptr));
+        bitmap.eraseColor(0);
+        if (info.colorType() == kRGBA_F16_SkColorType) {
+            // Drawing RGBA_F16 onto ARGB_8888 is not supported
+            skBitmap.readPixels(bitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()),
+                    bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
+        } else {
+            SkCanvas canvas(bitmap);
+            canvas.drawBitmap(skBitmap, 0.0f, 0.0f, nullptr);
+        }
+    }
+
+    sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
+            GraphicBuffer::USAGE_HW_TEXTURE |
+            GraphicBuffer::USAGE_SW_WRITE_NEVER |
+            GraphicBuffer::USAGE_SW_READ_NEVER,
+            std::string("Bitmap::allocateSkiaHardwareBitmap pid [") + std::to_string(getpid()) + "]");
+
+    status_t error = buffer->initCheck();
+    if (error < 0) {
+        ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
+        return nullptr;
+    }
+
+    //upload the bitmap into a texture
+    EGLDisplay display = eglGetCurrentDisplay();
+    LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
+                "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+                uirenderer::renderthread::EglManager::eglErrorString());
+    // We use an EGLImage to access the content of the GraphicBuffer
+    // The EGL image is later bound to a 2D texture
+    EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
+    AutoEglImage autoImage(display, clientBuffer);
+    if (autoImage.image == EGL_NO_IMAGE_KHR) {
+        ALOGW("Could not create EGL image, err =%s",
+                uirenderer::renderthread::EglManager::eglErrorString());
+        return nullptr;
+    }
+    AutoSkiaGlTexture glTexture;
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
+    GL_CHECKPOINT(MODERATE);
+
+    // glTexSubImage2D is synchronous in sense that it memcpy() from pointer that we provide.
+    // But asynchronous in sense that driver may upload texture onto hardware buffer when we first
+    // use it in drawing
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info.width(), info.height(), format, type,
+            bitmap.getPixels());
+    GL_CHECKPOINT(MODERATE);
+
+    // The fence is used to wait for the texture upload to finish
+    // properly. We cannot rely on glFlush() and glFinish() as
+    // some drivers completely ignore these API calls
+    AutoEglFence autoFence(display);
+    if (autoFence.fence == EGL_NO_SYNC_KHR) {
+        LOG_ALWAYS_FATAL("Could not create sync fence %#x", eglGetError());
+        return nullptr;
+    }
+    // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
+    // pipeline flush (similar to what a glFlush() would do.)
+    EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
+            EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
+    if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
+        LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
+        return nullptr;
+    }
+
+    grContext->resetContext(kTextureBinding_GrGLBackendState);
+
+    return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info()));
+}
+
 } /* namespace skiapipeline */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 36685dd..d5471de 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -19,6 +19,9 @@
 #include "SkiaPipeline.h"
 
 namespace android {
+
+class Bitmap;
+
 namespace uirenderer {
 namespace skiapipeline {
 
@@ -40,12 +43,15 @@
             FrameInfo* currentFrameInfo, bool* requireSwap) override;
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
     DeferredLayerUpdater* createTextureLayer() override;
-    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior) override;
+    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
+            renderthread::ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+    static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
+            SkBitmap& skBitmap);
 
 private:
     renderthread::EglManager& mEglManager;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 04aeb7c..89697d7 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -86,23 +86,17 @@
         textureMatrix.mapRect(&skiaSrcRect);
 
         if (skiaSrcRect.intersect(bufferRect)) {
-            SkPoint srcOrigin = SkPoint::Make(skiaSrcRect.fLeft, skiaSrcRect.fTop);
+            // we render in an offscreen buffer to scale and to avoid an issue b/62262733
+            // with reading incorrect data from EGLImage backed SkImage (likely a driver bug)
+            sk_sp<SkSurface> scaledSurface = SkSurface::MakeRenderTarget(
+                    grContext.get(), SkBudgeted::kYes, bitmap->info());
+            SkPaint paint;
+            paint.setBlendMode(SkBlendMode::kSrc);
+            scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect,
+                    SkRect::MakeWH(bitmap->width(), bitmap->height()), &paint);
+            image = scaledSurface->makeImageSnapshot();
 
-            // if we need to scale the result we must render to an offscreen buffer
-            if (bitmap->width() != skiaSrcRect.width()
-                    || bitmap->height() != skiaSrcRect.height()) {
-                sk_sp<SkSurface> scaledSurface = SkSurface::MakeRenderTarget(
-                        grContext.get(), SkBudgeted::kYes, bitmap->info());
-                SkPaint paint;
-                paint.setBlendMode(SkBlendMode::kSrc);
-                scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect,
-                        SkRect::MakeWH(bitmap->width(), bitmap->height()), &paint);
-                image = scaledSurface->makeImageSnapshot();
-                srcOrigin.set(0,0);
-            }
-
-            if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(),
-                                  srcOrigin.fX, srcOrigin.fY)) {
+            if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
                 copyResult = CopyResult::Success;
             }
         }
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 75f1adc..88293db 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -159,11 +159,11 @@
     GrContext* context = thread.getGrContext();
     if (context) {
         ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
-        SkBitmap skiaBitmap;
-        bitmap->getSkBitmap(&skiaBitmap);
-        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
-        SkImage_pinAsTexture(image.get(), context);
-        SkImage_unpinAsTexture(image.get(), context);
+        auto image = bitmap->makeImage();
+        if (image.get() && !bitmap->isHardware()) {
+            SkImage_pinAsTexture(image.get(), context);
+            SkImage_unpinAsTexture(image.get(), context);
+        }
     }
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index cf8b4dd..a0cce98 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -156,30 +156,25 @@
 }
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
-    SkBitmap skBitmap;
-    bitmap.getSkBitmap(&skBitmap);
-
-    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+    sk_sp<SkImage> image = bitmap.makeImage();
     SkPaint tmpPaint;
     mRecorder.drawImage(image, left, top, nonAAPaint(paint, &tmpPaint));
     // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
     // it is not safe to store a raw SkImage pointer, because the image object will be destroyed
     // when this function ends.
-    if (!skBitmap.isImmutable() && image.get() && !image->unique()) {
+    if (!bitmap.isImmutable() && image.get() && !image->unique()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
 }
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
         const SkPaint* paint) {
-    SkBitmap bitmap;
-    hwuiBitmap.getSkBitmap(&bitmap);
     SkAutoCanvasRestore acr(&mRecorder, true);
     concat(matrix);
-    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    sk_sp<SkImage> image = hwuiBitmap.makeImage();
     SkPaint tmpPaint;
     mRecorder.drawImage(image, 0, 0, nonAAPaint(paint, &tmpPaint));
-    if (!bitmap.isImmutable() && image.get() && !image->unique()) {
+    if (!hwuiBitmap.isImmutable() && image.get() && !image->unique()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
 }
@@ -187,14 +182,12 @@
 void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
         float dstBottom, const SkPaint* paint) {
-    SkBitmap bitmap;
-    hwuiBitmap.getSkBitmap(&bitmap);
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    sk_sp<SkImage> image = hwuiBitmap.makeImage();
     SkPaint tmpPaint;
     mRecorder.drawImageRect(image, srcRect, dstRect, nonAAPaint(paint, &tmpPaint));
-    if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty()
+    if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty()
             && !dstRect.isEmpty()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
@@ -202,11 +195,8 @@
 
 void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
         float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
-    SkBitmap bitmap;
-    hwuiBitmap.getSkBitmap(&bitmap);
-
     SkCanvas::Lattice lattice;
-    NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
+    NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
 
     lattice.fFlags = nullptr;
     int numFlags = 0;
@@ -223,11 +213,11 @@
 
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    sk_sp<SkImage> image = hwuiBitmap.makeImage();
 
     SkPaint tmpPaint;
     mRecorder.drawImageLattice(image.get(), lattice, dst, nonAAPaint(paint, &tmpPaint));
-    if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
+    if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
 }
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index d28e605..f1ef9e6 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -131,13 +131,15 @@
 void SkiaVulkanPipeline::onStop() {
 }
 
-bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) {
+bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
+        ColorMode colorMode) {
     if (mVkSurface) {
         mVkManager.destroySurface(mVkSurface);
         mVkSurface = nullptr;
     }
 
     if (surface) {
+        // TODO: handle color mode
         mVkSurface = mVkManager.createSurface(surface);
     }
 
@@ -158,6 +160,25 @@
     (*functor)(mode, nullptr);
 }
 
+sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
+        SkBitmap& skBitmap) {
+    //TODO: implement this function for Vulkan pipeline
+    //code below is a hack to avoid crashing because of missing HW Bitmap support
+    sp<GraphicBuffer> buffer = new GraphicBuffer(skBitmap.info().width(), skBitmap.info().height(),
+            PIXEL_FORMAT_RGBA_8888,
+            GraphicBuffer::USAGE_HW_TEXTURE |
+            GraphicBuffer::USAGE_SW_WRITE_NEVER |
+            GraphicBuffer::USAGE_SW_READ_NEVER,
+            std::string("SkiaVulkanPipeline::allocateHardwareBitmap pid [")
+            + std::to_string(getpid()) + "]");
+    status_t error = buffer->initCheck();
+    if (error < 0) {
+        ALOGW("SkiaVulkanPipeline::allocateHardwareBitmap() failed in GraphicBuffer.create()");
+        return nullptr;
+    }
+    return sk_sp<Bitmap>(new Bitmap(buffer.get(), skBitmap.info()));
+}
+
 } /* namespace skiapipeline */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index aab1d7a..3481312 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -41,12 +41,15 @@
             FrameInfo* currentFrameInfo, bool* requireSwap) override;
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
     DeferredLayerUpdater* createTextureLayer() override;
-    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior) override;
+    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
+            renderthread::ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+    static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
+            SkBitmap& skBitmap);
 
 private:
     renderthread::VulkanManager& mVkManager;
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 481932d..2c92924 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -296,14 +296,20 @@
         // TODO: avoid query, and cache values (or RRCS ptr) in program
         const RoundRectClipState* state = glop.roundRectClipState;
         const Rect& innerRect = state->innerRect;
-        glUniform4f(fill.program->getUniform("roundRectInnerRectLTRB"),
-                innerRect.left, innerRect.top,
-                innerRect.right, innerRect.bottom);
-        glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"),
-                1, GL_FALSE, &state->matrix.data[0]);
 
         // add half pixel to round out integer rect space to cover pixel centers
         float roundedOutRadius = state->radius + 0.5f;
+
+        // Divide by the radius to simplify the calculations in the fragment shader
+        // roundRectPos is also passed from vertex shader relative to top/left & radius
+        glUniform4f(fill.program->getUniform("roundRectInnerRectLTWH"),
+                innerRect.left / roundedOutRadius, innerRect.top / roundedOutRadius,
+                (innerRect.right - innerRect.left) / roundedOutRadius,
+                (innerRect.bottom - innerRect.top) / roundedOutRadius);
+
+        glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"),
+                1, GL_FALSE, &state->matrix.data[0]);
+
         glUniform1f(fill.program->getUniform("roundRectRadius"),
                 roundedOutRadius);
     }
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index cbc5163..e2a4a2a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -186,7 +186,8 @@
 
     mNativeSurface = surface;
 
-    bool hasSurface = mRenderPipeline->setSurface(surface, mSwapBehavior);
+    ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::Srgb;
+    bool hasSurface = mRenderPipeline->setSurface(surface, mSwapBehavior, colorMode);
 
     mFrameNumber = -1;
 
@@ -241,6 +242,10 @@
     mOpaque = opaque;
 }
 
+void CanvasContext::setWideGamut(bool wideGamut) {
+    mWideColorGamut = wideGamut;
+}
+
 bool CanvasContext::makeCurrent() {
     if (mStopped) return false;
 
@@ -437,8 +442,8 @@
         if (mNativeSurface.get()) {
             int durationUs;
             nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime();
-            if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::Vsync)) {
-                // Ignoring dequeue duration as it happened prior to vsync
+            if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) {
+                // Ignoring dequeue duration as it happened prior to frame render start
                 // and thus is not part of the frame.
                 swap.dequeueDuration = 0;
             } else {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 33eda96..76623f9 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -128,6 +128,7 @@
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     void setLightCenter(const Vector3& lightCenter);
     void setOpaque(bool opaque);
+    void setWideGamut(bool wideGamut);
     bool makeCurrent();
     void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
             int64_t syncQueued, RenderNode* target);
@@ -240,6 +241,7 @@
     nsecs_t mLastDropVsync = 0;
 
     bool mOpaque;
+    bool mWideColorGamut = false;
     BakedOpRenderer::LightInfo mLightInfo;
     FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 };
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 44af5fd..53d42a2 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -76,12 +76,16 @@
 static struct {
     bool bufferAge = false;
     bool setDamage = false;
+    bool noConfigContext = false;
+    bool pixelFormatFloat = false;
+    bool glColorSpace = false;
 } EglExtensions;
 
 EglManager::EglManager(RenderThread& thread)
         : mRenderThread(thread)
         , mEglDisplay(EGL_NO_DISPLAY)
         , mEglConfig(nullptr)
+        , mEglConfigWideGamut(nullptr)
         , mEglContext(EGL_NO_CONTEXT)
         , mPBufferSurface(EGL_NO_SURFACE)
         , mCurrentSurface(EGL_NO_SURFACE) {
@@ -116,7 +120,7 @@
         }
     }
 
-    loadConfig();
+    loadConfigs();
     createContext();
     createPBufferSurface();
     makeCurrent(mPBufferSurface);
@@ -143,6 +147,7 @@
 void EglManager::initExtensions() {
     auto extensions = StringUtils::split(
             eglQueryString(mEglDisplay, EGL_EXTENSIONS));
+
     // For our purposes we don't care if EGL_BUFFER_AGE is a result of
     // EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
     // under EGL_KHR_partial_update and we don't need the expanded scope
@@ -152,13 +157,17 @@
     EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update");
     LOG_ALWAYS_FATAL_IF(!extensions.has("EGL_KHR_swap_buffers_with_damage"),
             "Missing required extension EGL_KHR_swap_buffers_with_damage");
+
+    EglExtensions.glColorSpace = extensions.has("EGL_KHR_gl_colorspace");
+    EglExtensions.noConfigContext = extensions.has("EGL_KHR_no_config_context");
+    EglExtensions.pixelFormatFloat = extensions.has("EGL_EXT_pixel_format_float");
 }
 
 bool EglManager::hasEglContext() {
     return mEglDisplay != EGL_NO_DISPLAY;
 }
 
-void EglManager::loadConfig() {
+void EglManager::loadConfigs() {
     ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
     EGLint swapBehavior = (mSwapBehavior == SwapBehavior::Preserved)
             ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
@@ -175,19 +184,44 @@
             EGL_NONE
     };
 
-    EGLint num_configs = 1;
-    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
-            || num_configs != 1) {
+    EGLint numConfigs = 1;
+    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, numConfigs, &numConfigs)
+            || numConfigs != 1) {
         if (mSwapBehavior == SwapBehavior::Preserved) {
             // Try again without dirty regions enabled
             ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
             mSwapBehavior = SwapBehavior::Discard;
-            loadConfig();
+            loadConfigs();
+            return; // the call to loadConfigs() we just made picks the wide gamut config
         } else {
             // Failed to get a valid config
             LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
         }
     }
+
+    if (EglExtensions.pixelFormatFloat) {
+        // If we reached this point, we have a valid swap behavior
+        EGLint attribs16F[] = {
+                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+                EGL_RED_SIZE, 16,
+                EGL_GREEN_SIZE, 16,
+                EGL_BLUE_SIZE, 16,
+                EGL_ALPHA_SIZE, 16,
+                EGL_DEPTH_SIZE, 0,
+                EGL_STENCIL_SIZE, Stencil::getStencilSize(),
+                EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
+                EGL_NONE
+        };
+
+        numConfigs = 1;
+        if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs, &numConfigs)
+                || numConfigs != 1) {
+            LOG_ALWAYS_FATAL(
+                    "Device claims wide gamut support, cannot find matching config, error = %s",
+                    eglErrorString());
+        }
+    }
 }
 
 void EglManager::createContext() {
@@ -195,7 +229,9 @@
             EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
             EGL_NONE
     };
-    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
+    mEglContext = eglCreateContext(mEglDisplay,
+            EglExtensions.noConfigContext ? ((EGLConfig) nullptr) : mEglConfig,
+            EGL_NO_CONTEXT, attribs);
     LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
         "Failed to create context, error = %s", eglErrorString());
 }
@@ -210,18 +246,60 @@
     }
 }
 
-EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
+EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) {
     initialize();
 
+    wideColorGamut = wideColorGamut && EglExtensions.glColorSpace
+            && EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
+
+    // The color space we want to use depends on whether linear blending is turned
+    // on and whether the app has requested wide color gamut rendering. When wide
+    // color gamut rendering is off, the app simply renders in the display's native
+    // color gamut.
+    //
+    // When wide gamut rendering is off:
+    // - Blending is done by default in gamma space, which requires using a
+    //   linear EGL color space (the GPU uses the color values as is)
+    // - If linear blending is on, we must use the sRGB EGL color space (the
+    //   GPU will perform sRGB to linear and linear to SRGB conversions before
+    //   and after blending)
+    //
+    // When wide gamut rendering is on we cannot rely on the GPU performing
+    // linear blending for us. We use two different color spaces to tag the
+    // surface appropriately for SurfaceFlinger:
+    // - Gamma blending (default) requires the use of the scRGB-nl color space
+    // - Linear blending requires the use of the scRGB color space
+
+    // Not all Android targets support the EGL_GL_COLOR_SPACE_KHR extension
+    // We insert to placeholders to set EGL_GL_COLORSPACE_KHR and its value.
+    // According to section 3.4.1 of the EGL specification, the attributes
+    // list is considered empty if the first entry is EGL_NONE
     EGLint attribs[] = {
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
-            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR,
-            EGL_COLORSPACE, EGL_COLORSPACE_sRGB,
-#endif
+            EGL_NONE, EGL_NONE,
             EGL_NONE
     };
 
-    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, attribs);
+    if (EglExtensions.glColorSpace) {
+        attribs[0] = EGL_GL_COLORSPACE_KHR;
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+        if (wideColorGamut) {
+            attribs[1] = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT;
+        } else {
+            attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
+        }
+#else
+        if (wideColorGamut) {
+            // TODO: this should be using scRGB-nl, not scRGB, we need an extension for this
+            // TODO: in the meantime SurfaceFlinger just assumes that scRGB is scRGB-nl
+            attribs[1] = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT;
+        } else {
+            attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+        }
+#endif
+    }
+
+    EGLSurface surface = eglCreateWindowSurface(mEglDisplay,
+            wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
     LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
             "Failed to create EGLSurface for window %p, eglErr = %s",
             (void*) window, eglErrorString());
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 0251925..2982c23 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -39,7 +39,7 @@
 
     bool hasEglContext();
 
-    EGLSurface createSurface(EGLNativeWindowType window);
+    EGLSurface createSurface(EGLNativeWindowType window, bool wideColorGamut);
     void destroySurface(EGLSurface surface);
 
     void destroy();
@@ -68,7 +68,7 @@
 
     void initExtensions();
     void createPBufferSurface();
-    void loadConfig();
+    void loadConfigs();
     void createContext();
     EGLint queryBufferAge(EGLSurface surface);
 
@@ -76,6 +76,7 @@
 
     EGLDisplay mEglDisplay;
     EGLConfig mEglConfig;
+    EGLConfig mEglConfigWideGamut;
     EGLContext mEglContext;
     EGLSurface mPBufferSurface;
 
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 45f6718..46ac0d2 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -44,6 +44,12 @@
     Succeeded
 };
 
+enum class ColorMode {
+    Srgb,
+    WideColorGamut,
+    // Hdr
+};
+
 class Frame;
 
 class IRenderPipeline {
@@ -61,7 +67,7 @@
             FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
     virtual bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) = 0;
     virtual DeferredLayerUpdater* createTextureLayer() = 0;
-    virtual bool setSurface(Surface* window, SwapBehavior swapBehavior) = 0;
+    virtual bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
     virtual void onStop() = 0;
     virtual bool isSurfaceReady() = 0;
     virtual bool isContextReady() = 0;
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index e1ae585..e15d0eb 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -146,7 +146,7 @@
     }
 }
 
-bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) {
+bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior, ColorMode colorMode) {
 
     if (mEglSurface != EGL_NO_SURFACE) {
         mEglManager.destroySurface(mEglSurface);
@@ -154,7 +154,8 @@
     }
 
     if (surface) {
-        mEglSurface = mEglManager.createSurface(surface);
+        const bool wideColorGamut = colorMode == ColorMode::WideColorGamut;
+        mEglSurface = mEglManager.createSurface(surface, wideColorGamut);
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
@@ -267,6 +268,171 @@
     thread.renderState().invokeFunctor(functor, mode, nullptr);
 }
 
+#define FENCE_TIMEOUT 2000000000
+
+class AutoEglFence {
+public:
+    AutoEglFence(EGLDisplay display)
+            : mDisplay(display) {
+        fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
+    }
+
+    ~AutoEglFence() {
+        if (fence != EGL_NO_SYNC_KHR) {
+            eglDestroySyncKHR(mDisplay, fence);
+        }
+    }
+
+    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
+private:
+    EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+class AutoEglImage {
+public:
+    AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
+            : mDisplay(display) {
+        EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+        image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
+                EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+    }
+
+    ~AutoEglImage() {
+        if (image != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mDisplay, image);
+        }
+    }
+
+    EGLImageKHR image = EGL_NO_IMAGE_KHR;
+private:
+    EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+class AutoGlTexture {
+public:
+    AutoGlTexture(uirenderer::Caches& caches)
+            : mCaches(caches) {
+        glGenTextures(1, &mTexture);
+        caches.textureState().bindTexture(mTexture);
+    }
+
+    ~AutoGlTexture() {
+        mCaches.textureState().deleteTexture(mTexture);
+    }
+
+private:
+    uirenderer::Caches& mCaches;
+    GLuint mTexture = 0;
+};
+
+static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
+        GraphicBuffer& buffer, GLint format, GLint type) {
+    EGLDisplay display = eglGetCurrentDisplay();
+    LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
+                "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+                uirenderer::renderthread::EglManager::eglErrorString());
+    // We use an EGLImage to access the content of the GraphicBuffer
+    // The EGL image is later bound to a 2D texture
+    EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer.getNativeBuffer();
+    AutoEglImage autoImage(display, clientBuffer);
+    if (autoImage.image == EGL_NO_IMAGE_KHR) {
+        ALOGW("Could not create EGL image, err =%s",
+                uirenderer::renderthread::EglManager::eglErrorString());
+        return false;
+    }
+    AutoGlTexture glTexture(caches);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
+
+    GL_CHECKPOINT(MODERATE);
+
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
+            format, type, bitmap.getPixels());
+
+    GL_CHECKPOINT(MODERATE);
+
+    // The fence is used to wait for the texture upload to finish
+    // properly. We cannot rely on glFlush() and glFinish() as
+    // some drivers completely ignore these API calls
+    AutoEglFence autoFence(display);
+    if (autoFence.fence == EGL_NO_SYNC_KHR) {
+        LOG_ALWAYS_FATAL("Could not create sync fence %#x", eglGetError());
+        return false;
+    }
+    // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
+    // pipeline flush (similar to what a glFlush() would do.)
+    EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
+            EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
+    if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
+        LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
+        return false;
+    }
+    return true;
+}
+
+// TODO: handle SRGB sanely
+static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
+    switch (internalFormat) {
+    case GL_LUMINANCE:
+        return PIXEL_FORMAT_RGBA_8888;
+    case GL_SRGB8_ALPHA8:
+        return PIXEL_FORMAT_RGBA_8888;
+    case GL_RGBA:
+        return PIXEL_FORMAT_RGBA_8888;
+    case GL_RGB:
+        return PIXEL_FORMAT_RGB_565;
+    case GL_RGBA16F:
+        return PIXEL_FORMAT_RGBA_FP16;
+    default:
+        LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
+        return PIXEL_FORMAT_UNKNOWN;
+    }
+}
+
+sk_sp<Bitmap> OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread,
+        SkBitmap& skBitmap) {
+    renderThread.eglManager().initialize();
+    uirenderer::Caches& caches = uirenderer::Caches::getInstance();
+
+    const SkImageInfo& info = skBitmap.info();
+    if (info.colorType() == kUnknown_SkColorType || info.colorType() == kAlpha_8_SkColorType) {
+        ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
+        return nullptr;
+    }
+
+    bool needSRGB = uirenderer::transferFunctionCloseToSRGB(skBitmap.info().colorSpace());
+    bool hasLinearBlending = caches.extensions().hasLinearBlending();
+    GLint format, type, internalFormat;
+    uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
+            needSRGB && hasLinearBlending, &internalFormat, &format, &type);
+
+    PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
+    sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
+            GraphicBuffer::USAGE_HW_TEXTURE |
+            GraphicBuffer::USAGE_SW_WRITE_NEVER |
+            GraphicBuffer::USAGE_SW_READ_NEVER,
+            std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
+
+    status_t error = buffer->initCheck();
+    if (error < 0) {
+        ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
+        return nullptr;
+    }
+
+    SkBitmap bitmap;
+    if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
+            hasLinearBlending))) {
+        sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
+        bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
+    } else {
+        bitmap = skBitmap;
+    }
+
+    if (!uploadBitmapToGraphicBuffer(caches, bitmap, *buffer, format, type)) {
+        return nullptr;
+    }
+    return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info()));
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h
index 6df8be4..0e8c3f5 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.h
+++ b/libs/hwui/renderthread/OpenGLPipeline.h
@@ -44,7 +44,7 @@
             FrameInfo* currentFrameInfo, bool* requireSwap) override;
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
     DeferredLayerUpdater* createTextureLayer() override;
-    bool setSurface(Surface* window, SwapBehavior swapBehavior) override;
+    bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) override;
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
@@ -61,6 +61,8 @@
     static void destroyLayer(RenderNode* node);
     static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap);
     static void invokeFunctor(const RenderThread& thread, Functor* functor);
+    static sk_sp<Bitmap> allocateHardwareBitmap(RenderThread& thread,
+            SkBitmap& skBitmap);
 
 private:
     EglManager& mEglManager;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index eed5238..5a4695f 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -227,6 +227,18 @@
     post(task);
 }
 
+CREATE_BRIDGE2(setWideGamut, CanvasContext* context, bool wideGamut) {
+    args->context->setWideGamut(args->wideGamut);
+    return nullptr;
+}
+
+void RenderProxy::setWideGamut(bool wideGamut) {
+    SETUP_TASK(setWideGamut);
+    args->context = mContext;
+    args->wideGamut = wideGamut;
+    post(task);
+}
+
 int64_t* RenderProxy::frameInfo() {
     return mDrawFrameTask.frameInfo();
 }
@@ -664,7 +676,7 @@
 }
 
 CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) {
-    sk_sp<Bitmap> hardwareBitmap = Bitmap::allocateHardwareBitmap(*args->thread, *args->bitmap);
+    sk_sp<Bitmap> hardwareBitmap = args->thread->allocateHardwareBitmap(*args->bitmap);
     return hardwareBitmap.release();
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index b21772c..e1e2808 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,7 +69,7 @@
  */
 class ANDROID_API RenderProxy {
 public:
-    ANDROID_API RenderProxy(bool translucent, RenderNode* rootNode, IContextFactory* contextFactory);
+    ANDROID_API RenderProxy(bool opaque, RenderNode* rootNode, IContextFactory* contextFactory);
     ANDROID_API virtual ~RenderProxy();
 
     // Won't take effect until next EGLSurface creation
@@ -85,6 +85,7 @@
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     ANDROID_API void setLightCenter(const Vector3& lightCenter);
     ANDROID_API void setOpaque(bool opaque);
+    ANDROID_API void setWideGamut(bool wideGamut);
     ANDROID_API int64_t* frameInfo();
     ANDROID_API int syncAndDrawFrame();
     ANDROID_API void destroy();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 1450ec9..0554583 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,8 +16,12 @@
 
 #include "RenderThread.h"
 
-#include "../renderstate/RenderState.h"
-#include "../pipeline/skia/SkiaOpenGLReadback.h"
+#include "hwui/Bitmap.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/OpenGLPipeline.h"
+#include "pipeline/skia/SkiaOpenGLReadback.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
+#include "pipeline/skia/SkiaVulkanPipeline.h"
 #include "CanvasContext.h"
 #include "EglManager.h"
 #include "OpenGLReadback.h"
@@ -433,6 +437,22 @@
     return next;
 }
 
+sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) {
+    auto renderType = Properties::getRenderPipelineType();
+    switch (renderType) {
+        case RenderPipelineType::OpenGL:
+            return OpenGLPipeline::allocateHardwareBitmap(*this, skBitmap);
+        case RenderPipelineType::SkiaGL:
+            return skiapipeline::SkiaOpenGLPipeline::allocateHardwareBitmap(*this, skBitmap);
+        case RenderPipelineType::SkiaVulkan:
+            return skiapipeline::SkiaVulkanPipeline::allocateHardwareBitmap(*this, skBitmap);
+        default:
+            LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+            break;
+    }
+    return nullptr;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 9bc5985..4b5601c 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -24,6 +24,7 @@
 
 #include <GrContext.h>
 #include <cutils/compiler.h>
+#include <SkBitmap.h>
 #include <ui/DisplayInfo.h>
 #include <utils/Looper.h>
 #include <utils/Thread.h>
@@ -33,6 +34,7 @@
 
 namespace android {
 
+class Bitmap;
 class DisplayEventReceiver;
 
 namespace uirenderer {
@@ -104,6 +106,8 @@
 
     VulkanManager& vulkanManager() { return *mVkManager; }
 
+    sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap);
+
 protected:
     virtual bool threadLoop() override;
 
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index a7ebb68..4797dec 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -45,10 +45,8 @@
             skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
         });
 
-        SkBitmap bitmap;
         SkPaint paint;
-        hwuiBitmap->getSkBitmapForShaders(&bitmap);
-        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+        sk_sp<SkImage> image = hwuiBitmap->makeImage();
         sk_sp<SkShader> repeatShader = image->makeShader(
                 SkShader::TileMode::kRepeat_TileMode,
                 SkShader::TileMode::kRepeat_TileMode,
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index a461426..c246eba 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -75,9 +75,7 @@
     void doFrame(int frameNr) override { }
 
     sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
-        SkBitmap skBitmap;
-        bitmap.getSkBitmapForShaders(&skBitmap);
-        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+        sk_sp<SkImage> image = bitmap.makeImage();
         return image->makeShader(SkShader::TileMode::kClamp_TileMode,
                 SkShader::TileMode::kClamp_TileMode);
     }
diff --git a/libs/hwui/tests/unit/TextureCacheTests.cpp b/libs/hwui/tests/unit/TextureCacheTests.cpp
index 72384bf..ab740dd 100644
--- a/libs/hwui/tests/unit/TextureCacheTests.cpp
+++ b/libs/hwui/tests/unit/TextureCacheTests.cpp
@@ -31,7 +31,7 @@
     SkBitmap skBitmap;
     SkImageInfo info = SkImageInfo::Make(100, 100, kN32_SkColorType, kPremul_SkAlphaType);
     skBitmap.setInfo(info);
-    sk_sp<Bitmap> hwBitmap(Bitmap::allocateHardwareBitmap(renderThread, skBitmap));
+    sk_sp<Bitmap> hwBitmap(renderThread.allocateHardwareBitmap(skBitmap));
     cache.get(hwBitmap.get());
     ASSERT_EQ(GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture), initialCount + 1);
     cache.clear();
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d2d4b5b..9b74656 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -339,6 +339,12 @@
         (unsigned 64-bit {@linkplain ByteOrder#nativeOrder native-order} integer.)</td>
    </tr>
    <tr>
+    <td>FLAC</td>
+    <td>Metadata blocks</td>
+    <td class=NA>Not Used</td>
+    <td class=NA>Not Used</td>
+   </tr>
+   <tr>
     <td>MPEG-4</td>
     <td>Decoder-specific information from ESDS<sup>*</sup></td>
     <td class=NA>Not Used</td>
diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp
index ba3b482..3d98877 100644
--- a/media/jni/soundpool/SoundPoolThread.cpp
+++ b/media/jni/soundpool/SoundPoolThread.cpp
@@ -20,6 +20,8 @@
 
 #include "SoundPoolThread.h"
 
+static const int kMaxWorkers = 3;
+
 namespace android {
 
 void SoundPoolThread::write(SoundPoolMsg msg) {
@@ -31,14 +33,21 @@
     // if thread is quitting, don't add to queue
     if (mRunning) {
         mMsgQueue.push(msg);
-        mCondition.signal();
+        if (mNumWorkers < kMaxWorkers) {
+            if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
+                mNumWorkers++;
+                ALOGV("created worker thread");
+            }
+        }
     }
 }
 
 const SoundPoolMsg SoundPoolThread::read() {
     Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() == 0) {
-        mCondition.wait(mLock);
+    if (mMsgQueue.size() == 0) {
+        mNumWorkers--;
+        mCondition.signal();
+        return SoundPoolMsg(SoundPoolMsg::KILL, 0);
     }
     SoundPoolMsg msg = mMsgQueue[0];
     mMsgQueue.removeAt(0);
@@ -51,20 +60,20 @@
     if (mRunning) {
         mRunning = false;
         mMsgQueue.clear();
-        mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
-        mCondition.signal();
-        mCondition.wait(mLock);
+        mCondition.broadcast(); // wake up any blocked writers
+        while (mNumWorkers > 0) {
+            mCondition.wait(mLock);
+        }
     }
     ALOGV("return from quit");
 }
 
 SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
-    mSoundPool(soundPool)
+    mSoundPool(soundPool),
+    mNumWorkers(0),
+    mRunning(true)
 {
     mMsgQueue.setCapacity(maxMessages);
-    if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
-        mRunning = true;
-    }
 }
 
 SoundPoolThread::~SoundPoolThread()
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
index 7b3e1dd..5d7bf0c 100644
--- a/media/jni/soundpool/SoundPoolThread.h
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -58,6 +58,7 @@
     Condition               mCondition;
     Vector<SoundPoolMsg>    mMsgQueue;
     SoundPool*              mSoundPool;
+    int32_t                 mNumWorkers;
     bool                    mRunning;
 };
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
deleted file mode 100644
index b237021..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.os.AsyncTask;
-import android.os.BatteryManager;
-import android.os.BatteryStats;
-import android.os.BatteryStats.HistoryItem;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.text.format.Formatter;
-import android.util.SparseIntArray;
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.settingslib.graph.UsageView;
-
-public class BatteryInfo {
-
-    public String chargeLabelString;
-    public int batteryLevel;
-    public boolean discharging = true;
-    public long remainingTimeUs = 0;
-    public String batteryPercentString;
-    public String remainingLabel;
-    public String statusLabel;
-    private boolean mCharging;
-    private BatteryStats mStats;
-    private long timePeriod;
-
-    public interface Callback {
-        void onBatteryInfoLoaded(BatteryInfo info);
-    }
-
-    public void bindHistory(final UsageView view, BatteryDataParser... parsers) {
-        BatteryDataParser parser = new BatteryDataParser() {
-            SparseIntArray points = new SparseIntArray();
-
-            @Override
-            public void onParsingStarted(long startTime, long endTime) {
-                timePeriod = endTime - startTime - remainingTimeUs / 1000;
-                view.clearPaths();
-                view.configureGraph((int) (endTime - startTime), 100, remainingTimeUs != 0,
-                        mCharging);
-            }
-
-            @Override
-            public void onDataPoint(long time, HistoryItem record) {
-                points.put((int) time, record.batteryLevel);
-            }
-
-            @Override
-            public void onDataGap() {
-                if (points.size() > 1) {
-                    view.addPath(points);
-                }
-                points.clear();
-            }
-
-            @Override
-            public void onParsingDone() {
-                if (points.size() > 1) {
-                    view.addPath(points);
-                }
-            }
-        };
-        BatteryDataParser[] parserList = new BatteryDataParser[parsers.length + 1];
-        for (int i = 0; i < parsers.length; i++) {
-            parserList[i] = parsers[i];
-        }
-        parserList[parsers.length] = parser;
-        parse(mStats, remainingTimeUs, parserList);
-        final Context context = view.getContext();
-        String timeString = context.getString(R.string.charge_length_format,
-                Formatter.formatShortElapsedTime(context, timePeriod));
-        String remaining = "";
-        if (remainingTimeUs != 0) {
-            remaining = context.getString(R.string.remaining_length_format,
-                    Formatter.formatShortElapsedTime(context, remainingTimeUs / 1000));
-        }
-        view.setBottomLabels(new CharSequence[]{timeString, remaining});
-    }
-
-    public static void getBatteryInfo(final Context context, final Callback callback) {
-        BatteryInfo.getBatteryInfo(context, callback, false /* shortString */);
-    }
-
-    public static void getBatteryInfo(final Context context, final Callback callback,
-            boolean shortString) {
-        new AsyncTask<Void, Void, BatteryStats>() {
-            @Override
-            protected BatteryStats doInBackground(Void... params) {
-                BatteryStatsHelper statsHelper = new BatteryStatsHelper(context, true);
-                statsHelper.create((Bundle) null);
-                return statsHelper.getStats();
-            }
-
-            @Override
-            protected void onPostExecute(BatteryStats batteryStats) {
-                final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
-                Intent batteryBroadcast = context.registerReceiver(null,
-                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-                BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast,
-                        batteryStats, elapsedRealtimeUs, shortString);
-                callback.onBatteryInfoLoaded(batteryInfo);
-            }
-        }.execute();
-    }
-
-    public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
-                                             BatteryStats stats, long elapsedRealtimeUs) {
-        return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats, elapsedRealtimeUs,
-                false /* shortString */);
-    }
-
-    public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
-            BatteryStats stats, long elapsedRealtimeUs, boolean shortString) {
-        return getBatteryInfo(context, batteryBroadcast, stats, elapsedRealtimeUs, shortString,
-                stats.computeBatteryTimeRemaining(elapsedRealtimeUs), false);
-    }
-
-    public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
-            BatteryStats stats, long elapsedRealtimeUs, boolean shortString, long drainTimeUs,
-            boolean basedOnUsage) {
-        BatteryInfo info = new BatteryInfo();
-        info.mStats = stats;
-        info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
-        info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);
-        info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
-        final Resources resources = context.getResources();
-
-        info.statusLabel = Utils.getBatteryStatus(resources, batteryBroadcast);
-        if (!info.mCharging) {
-            if (drainTimeUs > 0) {
-                info.remainingTimeUs = drainTimeUs;
-                String timeString = Formatter.formatShortElapsedTime(context,
-                        drainTimeUs / 1000);
-                info.remainingLabel = resources.getString(
-                        shortString ?
-                                (basedOnUsage ?
-                                        R.string.power_remaining_duration_only_short_enhanced :
-                                        R.string.power_remaining_duration_only_short) :
-                                (basedOnUsage ?
-                                        R.string.power_remaining_duration_only_enhanced :
-                                        R.string.power_remaining_duration_only),
-                        timeString);
-                info.chargeLabelString = resources.getString(
-                        shortString ?
-                                R.string.power_discharging_duration_short :
-                                basedOnUsage ?
-                                        R.string.power_discharging_duration_enhanced :
-                                        R.string.power_discharging_duration,
-                        info.batteryPercentString, timeString);
-            } else {
-                info.remainingLabel = null;
-                info.chargeLabelString = info.batteryPercentString;
-            }
-        } else {
-            final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
-            final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
-                    BatteryManager.BATTERY_STATUS_UNKNOWN);
-            info.discharging = false;
-            if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
-                info.remainingTimeUs = chargeTime;
-                String timeString = Formatter.formatShortElapsedTime(context,
-                        chargeTime / 1000);
-                int resId = shortString ? R.string.power_charging_duration_short
-                        : R.string.power_charging_duration;
-                info.remainingLabel = resources.getString(
-                        R.string.power_remaining_charging_duration_only, timeString);
-                info.chargeLabelString = resources.getString(
-                        resId, info.batteryPercentString, timeString);
-            } else {
-                final String chargeStatusLabel = resources.getString(
-                        R.string.battery_info_status_charging_lower);
-                info.remainingLabel = null;
-                info.chargeLabelString = resources.getString(
-                        R.string.power_charging, info.batteryPercentString, chargeStatusLabel);
-            }
-        }
-        return info;
-    }
-
-    public interface BatteryDataParser {
-        void onParsingStarted(long startTime, long endTime);
-
-        void onDataPoint(long time, HistoryItem record);
-
-        void onDataGap();
-
-        void onParsingDone();
-    }
-
-    private static void parse(BatteryStats stats, long remainingTimeUs,
-            BatteryDataParser... parsers) {
-        long startWalltime = 0;
-        long endDateWalltime = 0;
-        long endWalltime = 0;
-        long historyStart = 0;
-        long historyEnd = 0;
-        byte lastLevel = -1;
-        long curWalltime = startWalltime;
-        long lastWallTime = 0;
-        long lastRealtime = 0;
-        int lastInteresting = 0;
-        int pos = 0;
-        boolean first = true;
-        if (stats.startIteratingHistoryLocked()) {
-            final HistoryItem rec = new HistoryItem();
-            while (stats.getNextHistoryLocked(rec)) {
-                pos++;
-                if (first) {
-                    first = false;
-                    historyStart = rec.time;
-                }
-                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
-                        || rec.cmd == HistoryItem.CMD_RESET) {
-                    // If there is a ridiculously large jump in time, then we won't be
-                    // able to create a good chart with that data, so just ignore the
-                    // times we got before and pretend like our data extends back from
-                    // the time we have now.
-                    // Also, if we are getting a time change and we are less than 5 minutes
-                    // since the start of the history real time, then also use this new
-                    // time to compute the base time, since whatever time we had before is
-                    // pretty much just noise.
-                    if (rec.currentTime > (lastWallTime + (180 * 24 * 60 * 60 * 1000L))
-                            || rec.time < (historyStart + (5 * 60 * 1000L))) {
-                        startWalltime = 0;
-                    }
-                    lastWallTime = rec.currentTime;
-                    lastRealtime = rec.time;
-                    if (startWalltime == 0) {
-                        startWalltime = lastWallTime - (lastRealtime - historyStart);
-                    }
-                }
-                if (rec.isDeltaData()) {
-                    if (rec.batteryLevel != lastLevel || pos == 1) {
-                        lastLevel = rec.batteryLevel;
-                    }
-                    lastInteresting = pos;
-                    historyEnd = rec.time;
-                }
-            }
-        }
-        stats.finishIteratingHistoryLocked();
-        endDateWalltime = lastWallTime + historyEnd - lastRealtime;
-        endWalltime = endDateWalltime + (remainingTimeUs / 1000);
-
-        int i = 0;
-        final int N = lastInteresting;
-
-        for (int j = 0; j < parsers.length; j++) {
-            parsers[j].onParsingStarted(startWalltime, endWalltime);
-        }
-        if (endDateWalltime > startWalltime && stats.startIteratingHistoryLocked()) {
-            final HistoryItem rec = new HistoryItem();
-            while (stats.getNextHistoryLocked(rec) && i < N) {
-                if (rec.isDeltaData()) {
-                    curWalltime += rec.time - lastRealtime;
-                    lastRealtime = rec.time;
-                    long x = (curWalltime - startWalltime);
-                    if (x < 0) {
-                        x = 0;
-                    }
-                    for (int j = 0; j < parsers.length; j++) {
-                        parsers[j].onDataPoint(x, rec);
-                    }
-                } else {
-                    long lastWalltime = curWalltime;
-                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
-                            || rec.cmd == HistoryItem.CMD_RESET) {
-                        if (rec.currentTime >= startWalltime) {
-                            curWalltime = rec.currentTime;
-                        } else {
-                            curWalltime = startWalltime + (rec.time - historyStart);
-                        }
-                        lastRealtime = rec.time;
-                    }
-
-                    if (rec.cmd != HistoryItem.CMD_OVERFLOW
-                            && (rec.cmd != HistoryItem.CMD_CURRENT_TIME
-                            || Math.abs(lastWalltime - curWalltime) > (60 * 60 * 1000))) {
-                        for (int j = 0; j < parsers.length; j++) {
-                            parsers[j].onDataGap();
-                        }
-                    }
-                }
-                i++;
-            }
-        }
-
-        stats.finishIteratingHistoryLocked();
-
-        for (int j = 0; j < parsers.length; j++) {
-            parsers[j].onParsingDone();
-        }
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 7f95379..5361b43 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -63,6 +63,7 @@
     private int mWifiBadge = NetworkBadging.BADGING_NONE;
 
     static final int[] WIFI_CONNECTION_STRENGTH = {
+            R.string.accessibility_no_wifi,
             R.string.accessibility_wifi_one_bar,
             R.string.accessibility_wifi_two_bars,
             R.string.accessibility_wifi_three_bars,
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
new file mode 100644
index 0000000..159b2a1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
@@ -0,0 +1,67 @@
+/*
+ * 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.settingslib.wifi;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provide utility functions for retrieving saved Wi-Fi configurations.
+ */
+public class WifiSavedConfigUtils {
+    /**
+     * Returns all the saved configurations on the device, including both Wi-Fi networks and
+     * Passpoint profiles, represented by {@link AccessPoint}.
+     *
+     * @param context The application context
+     * @param wifiManager An instance of {@link WifiManager}
+     * @return List of {@link AccessPoint}
+     */
+    public static List<AccessPoint> getAllConfigs(Context context, WifiManager wifiManager) {
+        List<AccessPoint> savedConfigs = new ArrayList<>();
+        List<WifiConfiguration> savedNetworks = wifiManager.getConfiguredNetworks();
+        for (WifiConfiguration network : savedNetworks) {
+            // Configuration for Passpoint network is configured temporary by WifiService for
+            // connection attempt only.  The underlying configuration is saved as Passpoint
+            // configuration, which will be retrieved with WifiManager#getPasspointConfiguration
+            // call below.
+            if (network.isPasspoint()) {
+                continue;
+            }
+            // Ephemeral networks are not saved to the persistent storage, ignore them.
+            if (network.isEphemeral()) {
+                continue;
+            }
+            savedConfigs.add(new AccessPoint(context, network));
+        }
+        try {
+            List<PasspointConfiguration> savedPasspointConfigs =
+                    wifiManager.getPasspointConfigurations();
+            for (PasspointConfiguration config : savedPasspointConfigs) {
+                savedConfigs.add(new AccessPoint(context, config));
+            }
+        } catch (UnsupportedOperationException e) {
+            // Passpoint not supported.
+        }
+        return savedConfigs;
+    }
+}
+
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 7a63b8a..20cc5a6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -95,8 +95,6 @@
 
     private WifiTrackerNetworkCallback mNetworkCallback;
 
-    private int mNumSavedNetworks;
-
     @GuardedBy("mLock")
     private boolean mRegistered;
 
@@ -399,9 +397,11 @@
     /**
      * Returns the number of saved networks on the device, regardless of whether the WifiTracker
      * is tracking saved networks.
+     * TODO(b/62292448): remove this function and update callsites to use WifiSavedConfigUtils
+     * directly.
      */
     public int getNumSavedNetworks() {
-        return mNumSavedNetworks;
+        return WifiSavedConfigUtils.getAllConfigs(mContext, mWifiManager).size();
     }
 
     public boolean isConnected() {
@@ -499,12 +499,10 @@
 
         final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
         if (configs != null) {
-            mNumSavedNetworks = 0;
             for (WifiConfiguration config : configs) {
                 if (config.selfAdded && config.numAssociation == 0) {
                     continue;
                 }
-                mNumSavedNetworks++;
                 AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
                 if (mLastInfo != null && mLastNetworkInfo != null) {
                     accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index d4ce40c..086e10c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -410,6 +410,7 @@
         validConfig.BSSID = BSSID_1;
 
         WifiConfiguration selfAddedNoAssociation = new WifiConfiguration();
+        selfAddedNoAssociation.ephemeral = true;
         selfAddedNoAssociation.selfAdded = true;
         selfAddedNoAssociation.numAssociation = 0;
         selfAddedNoAssociation.SSID = SSID_2;
@@ -746,4 +747,4 @@
 
         verifyNoMoreInteractions(mockWifiListener);
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
deleted file mode 100644
index cffece4..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
+++ /dev/null
@@ -1,168 +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.settingslib;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.BatteryManager;
-import android.os.BatteryStats;
-import android.os.SystemClock;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.AdditionalMatchers;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.AdditionalMatchers.*;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.when;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class BatteryInfoTest {
-    private static final String STATUS_FULL = "Full";
-    private static final String STATUS_CHARGING_NO_TIME = "Charging";
-    private static final String STATUS_CHARGING_TIME = "Charging - 2h left";
-    private static final int PLUGGED_IN = 1;
-    private static final long REMAINING_TIME_NULL = -1;
-    private static final long REMAINING_TIME = 2;
-    public static final String ENHANCED_STRING_SUFFIX = "left based on your usage";
-    private Intent mDisChargingBatteryBroadcast;
-    private Intent mChargingBatteryBroadcast;
-    private Context mRealContext;
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private BatteryStats mBatteryStats;
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Resources mResources;
-
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mDisChargingBatteryBroadcast = new Intent();
-        mDisChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_PLUGGED, 0);
-        mDisChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_LEVEL, 0);
-        mDisChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_SCALE, 100);
-        mDisChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_STATUS,
-                BatteryManager.BATTERY_STATUS_FULL);
-
-        mChargingBatteryBroadcast = new Intent();
-        mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_PLUGGED,
-                BatteryManager.BATTERY_PLUGGED_AC);
-        mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_LEVEL, 50);
-        mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_SCALE, 100);
-        mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_STATUS,
-                BatteryManager.BATTERY_STATUS_UNKNOWN);
-
-        when(mContext.getResources().getString(R.string.battery_info_status_full))
-                .thenReturn(STATUS_FULL);
-        when(mContext.getResources().getString(eq(R.string.power_charging), any(),
-                any())).thenReturn(STATUS_CHARGING_NO_TIME);
-        when(mContext.getResources().getString(eq(R.string.power_charging_duration), any(),
-                any())).thenReturn(STATUS_CHARGING_TIME);
-        mRealContext = RuntimeEnvironment.application;
-    }
-
-    @Test
-    public void testGetBatteryInfo_hasStatusLabel() {
-        doReturn(REMAINING_TIME_NULL).when(mBatteryStats).computeBatteryTimeRemaining(anyLong());
-        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */);
-
-        assertThat(info.statusLabel).isEqualTo(STATUS_FULL);
-    }
-
-    @Test
-    public void testGetBatteryInfo_doNotShowChargingMethod_hasRemainingTime() {
-        doReturn(REMAINING_TIME).when(mBatteryStats).computeChargeTimeRemaining(anyLong());
-        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */);
-
-        assertThat(info.chargeLabelString).isEqualTo(STATUS_CHARGING_TIME);
-    }
-
-    @Test
-    public void testGetBatteryInfo_doNotShowChargingMethod_noRemainingTime() {
-        doReturn(REMAINING_TIME_NULL).when(mBatteryStats).computeChargeTimeRemaining(anyLong());
-        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */);
-
-        assertThat(info.chargeLabelString).isEqualTo(STATUS_CHARGING_NO_TIME);
-    }
-
-    @Test
-    public void testGetBatteryInfo_pluggedIn_dischargingFalse() {
-        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */);
-
-        assertThat(info.discharging).isEqualTo(false);
-    }
-
-    @Test
-    public void testGetBatteryInfo_basedOnUsageTrue_usesUsageString() {
-        doReturn(mResources).when(mContext).getResources();
-        when(mResources.getString(eq(R.string.battery_info_status_full))).thenReturn("");
-        when(mResources.getString(eq(R.string.power_remaining_duration_only_enhanced), any()))
-                .thenReturn(ENHANCED_STRING_SUFFIX);
-        when(mResources.getString(eq(R.string.power_remaining_duration_only_short_enhanced), any()))
-                .thenReturn(ENHANCED_STRING_SUFFIX);
-        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */,
-                1000, true /* basedOnUsage */);
-        BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */,
-                1000, true /* basedOnUsage */);
-
-        assertThat(info.remainingLabel).contains(ENHANCED_STRING_SUFFIX);
-        assertThat(info2.remainingLabel).contains(ENHANCED_STRING_SUFFIX);
-    }
-
-    @Test
-    public void testGetBatteryInfo_basedOnUsageFalse_usesDefaultString() {
-        doReturn(mResources).when(mContext).getResources();
-        when(mResources.getString(eq(R.string.battery_info_status_full))).thenReturn("");
-        when(mResources.getString(not(eq(R.string.power_remaining_duration_only_enhanced)), any()))
-                .thenReturn(ENHANCED_STRING_SUFFIX);
-        when(mResources.getString(not(eq(R.string.power_remaining_duration_only_short_enhanced)),
-                any())).thenReturn("");
-        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */,
-                1000, false /* basedOnUsage */);
-        BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
-                mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */,
-                1000, false /* basedOnUsage */);
-
-        assertThat(info.remainingLabel).doesNotContain(ENHANCED_STRING_SUFFIX);
-        assertThat(info2.remainingLabel).doesNotContain(ENHANCED_STRING_SUFFIX);
-    }
-}
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index 92c5fcc..8e27edf 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -100,7 +100,7 @@
         // Rotate the screenshot to the current orientation
         if (rotation != ROTATION_FREEZE_0) {
             Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight,
-                    Bitmap.Config.ARGB_8888);
+                    Bitmap.Config.ARGB_8888, screenShot.hasAlpha(), screenShot.getColorSpace());
             Canvas canvas = new Canvas(unrotatedScreenShot);
             canvas.translate(unrotatedScreenShot.getWidth() / 2,
                     unrotatedScreenShot.getHeight() / 2);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3ee451a..e322acc 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -195,6 +195,9 @@
     <!-- to access instant apps -->
     <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" />
 
+    <!-- to change themes - light or dark -->
+    <uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
diff --git a/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big.xml b/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big.xml
index 84ccb7c..fd385fc 100644
--- a/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big.xml
+++ b/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -18,8 +18,7 @@
     android:height="18dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0">
-
     <path
-        android:fillColor="@color/clock_gray"
-        android:pathData="M22.0,5.7l-4.6,-3.9l-1.3,1.5l4.6,3.9L22.0,5.7zM7.9,3.4L6.6,1.9L2.0,5.7l1.3,1.5L7.9,3.4zM12.5,8.0L11.0,8.0l0.0,6.0l4.7,2.9l0.8,-1.2l-4.0,-2.4L12.5,8.0zM12.0,4.0c-5.0,0.0 -9.0,4.0 -9.0,9.0c0.0,5.0 4.0,9.0 9.0,9.0s9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0zM12.0,20.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.9 3.1,-7.0 7.0,-7.0c3.9,0.0 7.0,3.1 7.0,7.0C19.0,16.9 15.9,20.0 12.0,20.0z"/>
+        android:fillColor="?attr/bgProtectSecondaryTextColor"
+        android:pathData="M21.35,6.49c-0.35,0.42 -0.98,0.47 -1.4,0.12l-3.07,-2.57a1,1 0,1 1,1.29 -1.53l3.07,2.57c0.42,0.35 0.47,0.98 0.11,1.41zM7.24,2.63a1,1 0,0 0,-1.41 -0.13L2.77,5.07A0.996,0.996 0,1 0,4.05 6.6l3.06,-2.57c0.43,-0.35 0.48,-0.98 0.13,-1.4zM11.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v4.68c0,0.35 0.18,0.68 0.49,0.86l3.65,2.19c0.34,0.2 0.78,0.1 0.98,-0.24a0.71,0.71 0,0 0,-0.25 -0.99l-3.37,-2v-4.5c0,-0.41 -0.34,-0.75 -0.75,-0.75zM12,5.9c-3.91,0 -7.1,3.18 -7.1,7.1s3.19,7.1 7.1,7.1 7.1,-3.18 7.1,-7.1 -3.19,-7.1 -7.1,-7.1M12,4a9,9 0,1 1,-0.001 18.001A9,9 0,0 1,12 4z" />
 </vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/pin_divider.xml b/packages/SystemUI/res-keyguard/drawable/pin_divider.xml
new file mode 100644
index 0000000..39104b5
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/pin_divider.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/pin_divider_color" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 29c93d5..26a179a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -54,6 +54,7 @@
              android:textStyle="normal"
              android:inputType="textPassword"
              android:textSize="16sp"
+             android:textColor="?attr/bgProtectTextColor"
              android:textAppearance="?android:attr/textAppearanceMedium"
              android:imeOptions="flagForceAscii|actionDone"
              android:maxLength="500"
@@ -67,6 +68,7 @@
              android:contentDescription="@string/accessibility_ime_switch_button"
              android:clickable="true"
              android:padding="8dip"
+             android:tint="@color/background_protected"
              android:layout_gravity="end|center_vertical"
              android:background="?android:attr/selectableItemBackground"
              android:visibility="gone"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index e75f3c15..9a97162 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -54,6 +54,7 @@
                     android:layout_centerHorizontal="true"
                     android:layout_marginRight="72dp"
                     androidprv:scaledTextSize="28"
+                    android:textColor="?attr/bgProtectTextColor"
                     android:contentDescription="@string/keyguard_accessibility_pin_area"
                     />
             <ImageButton
@@ -65,19 +66,20 @@
                     android:clickable="true"
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
-                    android:paddingRight="8dp"
+                    android:paddingRight="0dp"
                     android:paddingLeft="24dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
                     android:layout_alignParentRight="true"
+                    android:tint="@color/pin_delete_color"
                     />
             <View
                     android:id="@+id/divider"
                     android:layout_width="match_parent"
                     android:layout_height="1dp"
                     android:layout_alignParentBottom="true"
-                    android:background="#28FFFFFF"
+                    android:background="@drawable/pin_divider"
                     />
         </com.android.keyguard.AlphaOptimizedRelativeLayout>
         <LinearLayout
@@ -203,6 +205,7 @@
                     android:layout_weight="1"
                     android:paddingBottom="11sp"
                     android:src="@drawable/ic_done_wht"
+                    style="@style/Keyguard.ImageButton.NumPadEnter"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_enter"
                     />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index 920498f..87b1ee7 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -41,7 +41,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal|top"
-                android:textColor="@color/clock_white"
+                android:textColor="?attr/bgProtectTextColor"
                 android:singleLine="true"
                 style="@style/widget_big_thin"
                 android:format12Hour="@string/keyguard_widget_12_hours_format"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index fd681ca..7d47881 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -66,6 +66,7 @@
                     android:layout_centerHorizontal="true"
                     android:layout_marginRight="72dp"
                     androidprv:scaledTextSize="28"
+                    android:textColor="?attr/bgProtectTextColor"
                     android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
                     />
             <ImageButton
@@ -77,19 +78,20 @@
                     android:clickable="true"
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
-                    android:paddingRight="8dp"
+                    android:paddingRight="0dp"
                     android:paddingLeft="24dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
                     android:layout_alignParentRight="true"
+                    android:tint="@color/pin_delete_color"
                     />
             <View
                     android:id="@+id/divider"
                     android:layout_width="match_parent"
                     android:layout_height="1dp"
                     android:layout_alignParentBottom="true"
-                    android:background="#28FFFFFF"
+                    android:background="@drawable/pin_divider"
                     />
         </RelativeLayout>
         <LinearLayout
@@ -211,6 +213,7 @@
                     android:layout_weight="1"
                     android:paddingBottom="11sp"
                     android:src="@drawable/ic_done_wht"
+                    style="@style/Keyguard.ImageButton.NumPadEnter"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_enter"
                     />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 040b429..aaa53ee 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -67,6 +67,7 @@
                     android:layout_centerHorizontal="true"
                     android:layout_marginRight="72dp"
                     androidprv:scaledTextSize="28"
+                    android:textColor="?attr/bgProtectTextColor"
                     android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
                     />
             <ImageButton
@@ -78,19 +79,20 @@
                     android:clickable="true"
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
-                    android:paddingRight="8dp"
+                    android:paddingRight="0dp"
                     android:paddingLeft="24dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
                     android:layout_alignParentRight="true"
+                    android:tint="@color/pin_delete_color"
                     />
             <View
                     android:id="@+id/divider"
                     android:layout_width="match_parent"
                     android:layout_height="1dp"
                     android:layout_alignParentBottom="true"
-                    android:background="#28FFFFFF"
+                    android:background="@drawable/pin_divider"
                     />
         </RelativeLayout>
         <LinearLayout
@@ -212,6 +214,7 @@
                     android:layout_weight="1"
                     android:paddingBottom="11sp"
                     android:src="@drawable/ic_done_wht"
+                    style="@style/Keyguard.ImageButton.NumPadEnter"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_enter"
                     />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index ed415b8..a0850f4 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -25,10 +25,11 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:gravity="center">
-    <TextClock android:id="@+id/date_view"
+    <com.android.systemui.statusbar.policy.DateView
+        android:id="@+id/date_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textColor="@color/clock_white"
+        android:textColor="?attr/bgProtectTextColor"
         style="@style/widget_label"
         android:letterSpacing="0.15"
         android:gravity="center"
@@ -38,7 +39,7 @@
         android:layout_height="wrap_content"
         android:drawablePadding="6dp"
         android:drawableStart="@drawable/ic_access_alarms_big"
-        android:textColor="@color/clock_gray"
+        android:textColor="?attr/bgProtectSecondaryTextColor"
         android:letterSpacing="0.15"
         style="@style/widget_label"
         android:layout_marginStart="6dp"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 51adc1e..44fae86 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -40,7 +40,7 @@
             android:layout_gravity="center_horizontal"
             android:layout_centerHorizontal="true"
             android:layout_alignParentTop="true"
-            android:textColor="@color/clock_white"
+            android:textColor="?attr/bgProtectTextColor"
             android:singleLine="true"
             style="@style/widget_big_thin"
             android:format12Hour="@string/keyguard_widget_12_hours_format"
@@ -73,7 +73,7 @@
             android:layout_marginTop="@dimen/date_owner_info_margin"
             android:layout_centerHorizontal="true"
             android:layout_below="@id/keyguard_status_area"
-            android:textColor="@color/clock_gray"
+            android:textColor="?attr/bgProtectSecondaryTextColor"
             android:textSize="@dimen/widget_label_font_size"
             android:letterSpacing="0.05"
             android:ellipsize="marquee"
diff --git a/packages/SystemUI/res-keyguard/values/attrs.xml b/packages/SystemUI/res-keyguard/values/attrs.xml
index 7cfe631..d3d60a1 100644
--- a/packages/SystemUI/res-keyguard/values/attrs.xml
+++ b/packages/SystemUI/res-keyguard/values/attrs.xml
@@ -35,9 +35,13 @@
         <attr name="android:gravity" />
         <attr name="dotSize" format="dimension" />
         <attr name="charPadding" format="dimension" />
+        <attr name="android:textColor" format="color" />
     </declare-styleable>
 
     <declare-styleable name="CarrierText">
         <attr name="allCaps" format="boolean" />
     </declare-styleable>
+
+    <attr name="pinDividerColor" format="color" />
+    <attr name="pinDeleteColor" format="color" />
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/colors.xml b/packages/SystemUI/res-keyguard/values/colors.xml
deleted file mode 100644
index 3998c5b..0000000
--- a/packages/SystemUI/res-keyguard/values/colors.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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>
-
-    <!-- Clock -->
-    <color name="clock_white">#ffffffff</color>
-    <color name="clock_gray">@*android:color/secondary_text_default_material_dark</color>
-</resources>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 53a559f..d7ff349 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -20,11 +20,11 @@
 <resources>
     <!-- Keyguard PIN pad styles -->
     <style name="Keyguard.TextView" parent="@android:style/Widget.DeviceDefault.TextView">
-        <item name="android:textColor">@*android:color/primary_device_default_light</item>
+        <item name="android:textColor">?attr/bgProtectSecondaryTextColor</item>
         <item name="android:textSize">@dimen/kg_status_line_font_size</item>
     </style>
     <style name="Keyguard.TextView.EmergencyButton" parent="@android:style/DeviceDefault.ButtonBar">
-        <item name="android:textColor">@*android:color/primary_device_default_light</item>
+        <item name="android:textColor">?attr/bgProtectSecondaryTextColor</item>
         <item name="android:textSize">@dimen/kg_status_line_font_size</item>
         <item name="android:background">@null</item>
     </style>
@@ -34,13 +34,16 @@
         <item name="android:background">@null</item>
         <item name="android:textSize">36sp</item>
         <item name="android:fontFamily">sans-serif-light</item>
-        <item name="android:textColor">#ffffffff</item>
+        <item name="android:textColor">?attr/bgProtectTextColor</item>
         <item name="android:paddingBottom">-16dp</item>
     </style>
+    <style name="Keyguard.ImageButton.NumPadEnter" parent="@android:style/Widget.ImageButton">
+        <item name="android:tint">?attr/bgProtectTextColor</item>
+    </style>
     <style name="Widget.TextView.NumPadKey.Klondike" parent="Widget.TextView.NumPadKey">
         <item name="android:textSize">12sp</item>
         <item name="android:fontFamily">sans-serif</item>
-        <item name="android:textColor">#80ffffff</item>
+        <item name="android:textColor">?attr/bgProtectSecondaryTextColor</item>
         <item name="android:paddingBottom">0dp</item>
     </style>
 
@@ -58,8 +61,9 @@
     </style>
 
     <style name="PasswordTheme" parent="@android:style/Theme.DeviceDefault">
-        <item name="android:colorControlNormal">#80ffffff</item>
-        <item name="android:colorControlActivated">#80ffffff</item>
+        <item name="android:textColor">?attr/bgProtectTextColor</item>
+        <item name="android:colorControlNormal">?attr/bgProtectTextColor</item>
+        <item name="android:colorControlActivated">?attr/bgProtectTextColor</item>
     </style>
 
     <style name="keyguard_presentation_theme" parent="@android:style/Theme.Material.NoActionBar.Fullscreen">
diff --git a/packages/SystemUI/res/color/background_protect_secondary.xml b/packages/SystemUI/res/color/background_protect_secondary.xml
new file mode 100644
index 0000000..26dc151
--- /dev/null
+++ b/packages/SystemUI/res/color/background_protect_secondary.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?attr/bgProtectSecondaryTextColor" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/background_protected.xml b/packages/SystemUI/res/color/background_protected.xml
new file mode 100644
index 0000000..ab8ed87
--- /dev/null
+++ b/packages/SystemUI/res/color/background_protected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?attr/bgProtectTextColor" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/pin_delete_color.xml b/packages/SystemUI/res/color/pin_delete_color.xml
new file mode 100644
index 0000000..bb8b8e3
--- /dev/null
+++ b/packages/SystemUI/res/color/pin_delete_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="0.61" android:color="?attr/bgProtectTextColor" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/pin_divider_color.xml b/packages/SystemUI/res/color/pin_divider_color.xml
new file mode 100644
index 0000000..ca5f431
--- /dev/null
+++ b/packages/SystemUI/res/color/pin_divider_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="0.45" android:color="?attr/bgProtectSecondaryTextColor" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_access_alarms_small.xml b/packages/SystemUI/res/drawable/ic_access_alarms_small.xml
index b94cc8e..f6e5ceb 100644
--- a/packages/SystemUI/res/drawable/ic_access_alarms_small.xml
+++ b/packages/SystemUI/res/drawable/ic_access_alarms_small.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -17,10 +17,8 @@
     android:width="16dp"
     android:height="16dp"
     android:viewportWidth="24.0"
-    android:viewportHeight="24.0"
-    android:tint="?android:attr/textColorTertiary">
-
+    android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M22.0,5.7l-4.6,-3.9l-1.3,1.5l4.6,3.9L22.0,5.7zM7.9,3.4L6.6,1.9L2.0,5.7l1.3,1.5L7.9,3.4zM12.5,8.0L11.0,8.0l0.0,6.0l4.7,2.9l0.8,-1.2l-4.0,-2.4L12.5,8.0zM12.0,4.0c-5.0,0.0 -9.0,4.0 -9.0,9.0c0.0,5.0 4.0,9.0 9.0,9.0s9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0zM12.0,20.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.9 3.1,-7.0 7.0,-7.0c3.9,0.0 7.0,3.1 7.0,7.0C19.0,16.9 15.9,20.0 12.0,20.0z"/>
+        android:pathData="M21.35,6.49c-0.35,0.42 -0.98,0.47 -1.4,0.12l-3.07,-2.57a1,1 0,1 1,1.29 -1.53l3.07,2.57c0.42,0.35 0.47,0.98 0.11,1.41zM7.24,2.63a1,1 0,0 0,-1.41 -0.13L2.77,5.07A0.996,0.996 0,1 0,4.05 6.6l3.06,-2.57c0.43,-0.35 0.48,-0.98 0.13,-1.4zM11.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v4.68c0,0.35 0.18,0.68 0.49,0.86l3.65,2.19c0.34,0.2 0.78,0.1 0.98,-0.24a0.71,0.71 0,0 0,-0.25 -0.99l-3.37,-2v-4.5c0,-0.41 -0.34,-0.75 -0.75,-0.75zM12,5.9c-3.91,0 -7.1,3.18 -7.1,7.1s3.19,7.1 7.1,7.1 7.1,-3.18 7.1,-7.1 -3.19,-7.1 -7.1,-7.1M12,4a9,9 0,1 1,-0.001 18.001A9,9 0,0 1,12 4z"
+        android:fillColor="#FFFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_saver.xml b/packages/SystemUI/res/drawable/ic_data_saver.xml
index 64bbff0..0f027ee 100644
--- a/packages/SystemUI/res/drawable/ic_data_saver.xml
+++ b/packages/SystemUI/res/drawable/ic_data_saver.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,18 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,19.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.5 2.6,-6.4 6.0,-6.9L11.0,2.0C5.9,2.5 2.0,6.8 2.0,12.0c0.0,5.5 4.5,10.0 10.0,10.0c3.3,0.0 6.2,-1.6 8.1,-4.1l-2.6,-1.5C16.2,18.0 14.2,19.0 12.0,19.0z"/>
+        android:pathData="M16,12c0,0.55 -0.45,1 -1,1h-2v2c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1v-2L9,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h2L11,9c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v2h2c0.55,0 1,0.45 1,1zM17.69,16.87a7.437,7.437 0,0 1,-5.93 2.63c-3.82,-0.12 -7.03,-3.25 -7.25,-7.07 -0.21,-3.84 2.48,-7.1 6.07,-7.79 0.24,-0.04 0.42,-0.24 0.42,-0.48L11,2.62c0,-0.3 -0.27,-0.55 -0.57,-0.5A10.02,10.02 0,0 0,2.09 13.4c0.59,4.4 4.16,7.94 8.56,8.52a9.99,9.99 0,0 0,9.14 -3.65,0.5 0.5,0 0,0 -0.15,-0.74l-1.32,-0.76a0.469,0.469 0,0 0,-0.63 0.1z"
+        android:fillColor="#FFFFFFFF"/>
     <path
-        android:fillColor="#54FFFFFF"
-        android:pathData="M13.0,2.0l0.0,3.0c3.4,0.5 6.0,3.4 6.0,6.9c0.0,0.9 -0.2,1.8 -0.5,2.5l2.6,1.5c0.6,-1.2 0.9,-2.6 0.9,-4.1C22.0,6.8 18.0,2.6 13.0,2.0z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M16.0,11.0l0.0,2.0 -3.0,0.0 0.0,3.0 -2.0,0.0 0.0,-3.0 -3.0,0.0 0.0,-2.0 3.0,0.0 0.0,-3.0 2.0,0.0 0.0,3.0z"/>
+        android:pathData="M13.41,4.64a0.493,0.493 0,0 1,-0.41 -0.48L13,2.62c0,-0.3 0.27,-0.55 0.57,-0.5C18.35,2.88 22,7.01 22,12c0,1.23 -0.23,2.41 -0.64,3.5 -0.11,0.28 -0.45,0.4 -0.72,0.24l-1.33,-0.77a0.484,0.484 0,0 1,-0.21 -0.59c0.25,-0.75 0.39,-1.55 0.39,-2.38 0.01,-3.65 -2.62,-6.69 -6.08,-7.36z"
+        android:fillColor="#54FFFFFF" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_saver_off.xml b/packages/SystemUI/res/drawable/ic_data_saver_off.xml
index 3001ad9..29e6c91 100644
--- a/packages/SystemUI/res/drawable/ic_data_saver_off.xml
+++ b/packages/SystemUI/res/drawable/ic_data_saver_off.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -21,8 +21,5 @@
         android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,19.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.5 2.6,-6.4 6.0,-6.9L11.0,2.0C5.9,2.5 2.0,6.8 2.0,12.0c0.0,5.5 4.5,10.0 10.0,10.0c3.3,0.0 6.2,-1.6 8.1,-4.1l-2.6,-1.5C16.2,18.0 14.2,19.0 12.0,19.0z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.0,2.0l0.0,3.0c3.4,0.5 6.0,3.4 6.0,6.9c0.0,0.9 -0.2,1.8 -0.5,2.5l2.6,1.5c0.6,-1.2 0.9,-2.6 0.9,-4.1C22.0,6.8 18.0,2.6 13.0,2.0z"/>
+        android:pathData="M18.32,16.75l1.32,0.76c0.26,0.15 0.34,0.51 0.15,0.74 -2.09,2.6 -5.44,4.14 -9.14,3.65 -4.4,-0.58 -7.96,-4.12 -8.56,-8.52C1.34,7.8 5.21,2.95 10.43,2.12c0.3,-0.05 0.57,0.2 0.57,0.5v1.53c0,0.24 -0.18,0.44 -0.41,0.49 -3.6,0.69 -6.29,3.95 -6.07,7.79 0.21,3.82 3.43,6.95 7.25,7.07 2.37,0.08 4.51,-0.96 5.93,-2.63a0.48,0.48 0,0 1,0.62 -0.12zM19.5,12c0,0.83 -0.14,1.63 -0.39,2.38 -0.08,0.23 0.01,0.47 0.21,0.59l1.33,0.77c0.26,0.15 0.61,0.04 0.72,-0.24 0.4,-1.09 0.63,-2.27 0.63,-3.5 0,-4.99 -3.65,-9.12 -8.43,-9.88 -0.3,-0.04 -0.57,0.2 -0.57,0.5v1.53c0,0.24 0.18,0.44 0.41,0.48 3.46,0.68 6.09,3.72 6.09,7.37z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot.xml b/packages/SystemUI/res/drawable/ic_hotspot.xml
new file mode 100644
index 0000000..8450bf6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_hotspot.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <group
+        android:translateY="-0.32">
+        <path
+            android:pathData="M12,11c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,13a6,6 0,0 0,-6.75 -5.95c-2.62,0.32 -4.78,2.41 -5.18,5.02 -0.32,2.14 0.49,4.11 1.92,5.39 0.48,0.43 1.24,0.33 1.56,-0.23 0.24,-0.42 0.14,-0.94 -0.22,-1.26a3.99,3.99 0,0 1,-1.22 -3.94,3.954 3.954,0 0,1 2.9,-2.91A4.007,4.007 0,0 1,16 13c0,1.18 -0.51,2.23 -1.33,2.96 -0.36,0.33 -0.47,0.85 -0.23,1.27 0.31,0.54 1.04,0.69 1.5,0.28A5.97,5.97 0,0 0,18 13zM10.83,3.07c-4.62,0.52 -8.35,4.33 -8.78,8.96a9.966,9.966 0,0 0,4.02 9.01c0.48,0.35 1.16,0.2 1.46,-0.31 0.25,-0.43 0.14,-0.99 -0.26,-1.29 -2.28,-1.69 -3.65,-4.55 -3.16,-7.7 0.54,-3.5 3.46,-6.29 6.98,-6.68C15.91,4.51 20,8.28 20,13c0,2.65 -1.29,4.98 -3.27,6.44 -0.4,0.3 -0.51,0.85 -0.26,1.29 0.3,0.52 0.98,0.66 1.46,0.31A9.96,9.96 0,0 0,22 13c0,-5.91 -5.13,-10.62 -11.17,-9.93z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_disable.xml b/packages/SystemUI/res/drawable/ic_hotspot_disable.xml
deleted file mode 100644
index 2570483..0000000
--- a/packages/SystemUI/res/drawable/ic_hotspot_disable.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:alpha="1.0"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="ic_hotspot"
-        android:translateX="23.9778"
-        android:translateY="24.26443" >
-        <group
-            android:name="ic_hotspot_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -38.4077911377,30.8523712158 -38.4077911377,30.8523712158 c 0.0,0.0 6.97125244141,7.33258056641 6.97125244141,7.33258056641 c 0.0,0.0 -2.4169921875,2.57838439941 -2.4169921875,2.57838439941 c 0.0,0.0 -6.77128601074,-6.82850646973 -6.77128601074,-6.82850646973 c 0.0,0.0 -32.6199798584,25.1699066162 -32.6199798584,25.1699066162 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 27.6589050293,-22.6579437256 27.6589050293,-22.6579437256 c 0.0,0.0 -30.8645172119,-34.00390625 -30.8645172119,-34.00390625 c 0.0,0.0 2.70756530762,-1.99278259277 2.70756530762,-1.99278259277 c 0.0,0.0 1.53030395508,-0.876571655273 1.53030395508,-0.876571655274 c 0.0,0.0 2.85780334473,-3.12069702148 2.85780334473,-3.12069702148 c 0.0,0.0 0.659332275391,0.664688110352 0.659332275391,0.664688110351 c 0.0,0.0 -3.13299560547,2.82977294922 -3.13299560547,2.82977294922 c 0.0,0.0 29.0108337402,34.4080963135 29.0108337402,34.4080963135 c 0.0,0.0 42.8175811768,-34.3554534912 42.8175811768,-34.3554534912 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 4.44044494629,2.24310302734 c 0.0,0.0 0.0875396728516,0.112457275391 0.0875396728516,0.112457275391 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="0"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="hotspot"
-                android:translateX="23.481"
-                android:translateY="18.71151" >
-                <group
-                    android:name="circles"
-                    android:translateX="-0.23909"
-                    android:translateY="-0.10807" >
-                    <path
-                        android:name="path_3"
-                        android:pathData="M -0.0042724609375,-2.64895629883 c -2.20922851562,0.0 -4.0,1.791015625 -4.0,4.0 c 0.0,2.20922851562 1.79077148438,4.0 4.0,4.0 c 2.208984375,0.0 4.0,-1.79077148438 4.0,-4.0 c 0.0,-2.208984375 -1.791015625,-4.0 -4.0,-4.0 Z M 11.9957275391,1.35104370117 c 0.0,-6.626953125 -5.373046875,-12.0 -12.0,-12.0 c -6.62719726562,0.0 -12.0,5.373046875 -12.0,12.0 c 0.0,4.43603515625 2.41381835938,8.30004882812 5.99194335938,10.3771972656 c 0.0,0.0 2.01586914062,-3.48217773438 2.01586914062,-3.48217773438 c -2.38500976562,-1.38500976562 -4.0078125,-3.93798828125 -4.0078125,-6.89501953125 c 0.0,-4.41796875 3.58178710938,-8.0 8.0,-8.0 c 4.41796875,0.0 8.0,3.58203125 8.0,8.0 c 0.0,2.95703125 -1.623046875,5.51000976562 -4.00805664062,6.89501953125 c 0.0,0.0 2.01586914062,3.48217773438 2.01586914062,3.48217773438 c 3.578125,-2.0771484375 5.9921875,-5.94116210938 5.9921875,-10.3771972656 Z M -0.0042724609375,-18.6489562988 c -11.0451660156,0.0 -20.0,8.9541015625 -20.0,20.0 c 0.0,7.39306640625 4.02099609375,13.8330078125 9.98779296875,17.2951660156 c 0.0,0.0 2.00219726562,-3.458984375 2.00219726562,-3.458984375 c -4.77319335938,-2.77001953125 -7.98999023438,-7.92211914062 -7.98999023438,-13.8361816406 c 0.0,-8.8369140625 7.16381835938,-16.0 16.0,-16.0 c 8.83595275879,0.0 16.0000152588,7.1630859375 16.0000152588,16.0 c 0.0,5.9140625 -3.21704101562,11.0661621094 -7.990234375,13.8361816406 c 0.0,0.0 2.00219726562,3.458984375 2.00219726563,3.458984375 c 5.966796875,-3.46215820312 9.98803710937,-9.90209960938 9.98803710938,-17.2951660156 c 0.0,-11.0458984375 -8.955078125,-20.0 -20.0000152588,-20.0 Z"
-                        android:fillColor="#FFFFFFFF"
-                        android:fillAlpha="1" />
-                </group>
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
deleted file mode 100644
index 7a99630..0000000
--- a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_hotspot"
-        android:translateX="23.97354"
-        android:translateY="24.26306" >
-        <group
-            android:name="ic_hotspot_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -38.4077911377,30.8523712158 -38.4077911377,30.8523712158 c 0.0,0.0 43.1884765625,43.515335083 43.1884765625,43.515335083 c 0.0,0.0 -2.4169921875,2.57838439941 -2.4169921875,2.57838439941 c 0.0,0.0 -42.9885101318,-43.0112609863 -42.9885101318,-43.0112609863 c 0.0,0.0 -32.6199798584,25.1699066162 -32.6199798584,25.1699066162 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 27.6589050293,-22.6579437256 27.6589050293,-22.6579437256 c 0.0,0.0 -30.8645172119,-34.00390625 -30.8645172119,-34.00390625 c 0.0,0.0 2.70756530762,-1.99278259277 2.70756530762,-1.99278259277 c 0.0,0.0 1.53030395508,-0.876571655273 1.53030395508,-0.876571655274 c 0.0,0.0 2.85780334473,-3.12069702148 2.85780334473,-3.12069702148 c 0.0,0.0 13.0984039307,13.025604248 13.0984039307,13.025604248 c 0.0,0.0 -3.13299560547,2.82977294922 -3.13299560547,2.82977294922 c 0.0,0.0 16.571762085,22.0471801758 16.571762085,22.0471801758 c 0.0,0.0 42.8175811768,-34.3554534912 42.8175811768,-34.3554534912 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 4.44044494629,2.24310302734 c 0.0,0.0 35.4000396729,35.3999633789 35.4000396729,35.3999633789 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="1"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="hotspot"
-                android:translateX="23.481"
-                android:translateY="18.71151" >
-                <group
-                    android:name="circles"
-                    android:translateX="-0.23909"
-                    android:translateY="-0.10807" >
-                    <path
-                        android:name="circle_3"
-                        android:pathData="M 0.0843505859375,-2.93901062012 c -2.30102539062,0.0 -4.16702270508,1.86602783203 -4.16702270508,4.16702270508 c 0.0,2.29898071289 1.86599731445,4.16598510742 4.16702270508,4.16598510742 c 2.29998779297,0.0 4.16598510742,-1.86700439453 4.16598510742,-4.16598510742 c 0.0,-2.30099487305 -1.86599731445,-4.16702270508 -4.16598510742,-4.16702270508 Z M 11.1185302734,5.83390808105 c 0.0,0.0 0.0009765625,0.00100708007812 0.0009765625,0.00100708007812 c 0.14501953125,-0.356994628906 0.27099609375,-0.725006103516 0.382995605469,-1.09799194336 c 0.0570068359375,-0.195007324219 0.101013183594,-0.394989013672 0.149017333984,-0.595001220703 c 0.0690002441406,-0.281005859375 0.126983642578,-0.563995361328 0.175994873047,-0.851989746094 c 0.0270080566406,-0.169006347656 0.0559997558594,-0.337005615234 0.0759887695313,-0.509002685547 c 0.0580139160156,-0.468017578125 0.0970153808594,-0.942993164062 0.0970153808593,-1.4280090332 c 0.0,0.0 0.0,-0.00100708007812 0.0,-0.00100708007812 c 0.0,-5.03900146484 -3.11099243164,-9.3450012207 -7.5119934082,-11.1229858398 c -0.00601196289062,-0.00299072265625 -0.0130004882812,-0.0050048828125 -0.0190124511719,-0.00701904296875 c -0.686004638672,-0.275970458984 -1.39999389648,-0.492980957031 -2.14099121094,-0.638977050781 c -0.072998046875,-0.0150146484375 -0.149017333984,-0.02099609375 -0.222991943359,-0.0339965820313 c -0.302001953125,-0.0540161132812 -0.605010986328,-0.106018066406 -0.916015625,-0.136016845703 c -0.389984130859,-0.0390014648438 -0.786987304688,-0.0599975585938 -1.18899536133,-0.0599975585937 c -0.402008056641,0.0 -0.799011230469,0.02099609375 -1.19000244141,0.0599975585937 c -0.304992675781,0.0299987792969 -0.602996826172,0.0809936523438 -0.901000976563,0.132995605469 c -0.0790100097656,0.0150146484375 -0.160003662109,0.02099609375 -0.238006591797,0.0370178222656 c -0.368988037109,0.0719909667969 -0.730987548828,0.164001464844 -1.08700561523,0.269989013672 c -0.00299072265625,0.00100708007812 -0.0059814453125,0.00201416015625 -0.00900268554687,0.0020141601562 c -0.351989746094,0.10498046875 -0.694000244141,0.226989746094 -1.0309753418,0.361999511719 c -0.0110168457031,0.00399780273438 -0.0220031738281,0.00698852539062 -0.0320129394531,0.0119934082031 c -4.40200805664,1.77798461914 -7.51098632812,6.083984375 -7.5119934082,11.1229858398 c 0.0,0.00799560546875 0.00198364257812,0.0160217285156 0.0019836425781,0.0240173339844 c 0.00100708007812,0.475006103516 0.0380249023438,0.940002441406 0.0950012207032,1.39898681641 c 0.02001953125,0.175994873047 0.0490112304688,0.348999023438 0.0780029296875,0.523010253906 c 0.0469970703125,0.281982421875 0.105010986328,0.557983398438 0.171997070312,0.833984375 c 0.0480041503906,0.204010009766 0.093017578125,0.410003662109 0.152008056641,0.610015869141 c 0.110992431641,0.372009277344 0.238006591797,0.736999511719 0.382019042969,1.09298706055 c 0.0,0.0 0.0009765625,0.0 0.0009765625,0.0 c 1.00701904297,2.48400878906 2.81301879883,4.56100463867 5.11001586914,5.89501953125 c 0.0,0.0 2.01599121094,-3.48300170898 2.01599121094,-3.48300170898 c -2.03900146484,-1.18402099609 -3.5119934082,-3.22500610352 -3.89898681641,-5.63900756836 c 0.0,0.0 0.0009765625,-0.00100708007812 0.0009765625,-0.00100708007812 c -0.0220031738281,-0.130981445312 -0.0369873046875,-0.265991210938 -0.052978515625,-0.399993896484 c -0.0290222167969,-0.274993896484 -0.0570068359375,-0.552001953125 -0.0570068359375,-0.834991455078 c 0.0,0.0 0.0,-0.0190124511719 0.0,-0.0190124511719 c 0.0,-3.98999023438 2.92498779297,-7.28900146484 6.74398803711,-7.89199829102 c 0.0,0.0 0.0180053710938,0.0169982910156 0.0180053710938,0.0169982910156 c 0.404998779297,-0.0639953613281 0.81298828125,-0.125 1.23599243164,-0.125 c 0.0,0.0 0.00201416015625,0.0 0.00201416015624,0.0 c 0.0,0.0 0.00299072265625,0.0 0.00299072265626,0.0 c 0.423004150391,0.0 0.830017089844,0.0610046386719 1.23501586914,0.125 c 0.0,0.0 0.0169982910156,-0.0180053710938 0.0169982910156,-0.0180053710938 c 3.81997680664,0.60400390625 6.74499511719,3.90301513672 6.74499511719,7.89199829102 c 0.0,0.292999267578 -0.0280151367188,0.578002929688 -0.0589904785156,0.861999511719 c -0.0150146484375,0.132019042969 -0.0290222167969,0.264007568359 -0.051025390625,0.393005371094 c -0.385986328125,2.41500854492 -1.85897827148,4.45599365234 -3.89797973633,5.64001464844 c 0.0,0.0 2.01599121094,3.48300170898 2.01599121094,3.48300170898 c 2.29699707031,-1.33401489258 4.10299682617,-3.41101074219 5.11001586914,-5.89602661133 Z M 19.9300231934,2.95698547363 c 0.0059814453125,-0.0659790039062 0.0159912109375,-0.130981445312 0.02099609375,-0.196990966797 c 0.031982421875,-0.462005615234 0.0479736328125,-0.928009033203 0.0489807128906,-1.39700317383 c 0,0.0 0,-0.00997924804688 0,-0.00997924804687 c 0,0.0 0,-0.00100708007812 0,-0.00100708007813 c 0,-7.22500610352 -3.84399414062,-13.5360107422 -9.58599853516,-17.0500183105 c -1.06500244141,-0.652984619141 -2.19299316406,-1.20599365234 -3.37799072266,-1.65197753906 c -0.157989501953,-0.0599975585938 -0.317016601562,-0.118011474609 -0.476989746094,-0.174011230469 c -0.317016601562,-0.110992431641 -0.634002685547,-0.218994140625 -0.9580078125,-0.31298828125 c -0.470001220703,-0.139007568359 -0.944000244141,-0.264007568359 -1.4280090332,-0.368011474609 c -0.186004638672,-0.0390014648438 -0.376983642578,-0.0669860839844 -0.565002441406,-0.101013183594 c -0.414001464844,-0.0759887695312 -0.832000732422,-0.140991210938 -1.25500488281,-0.190979003906 c -0.184997558594,-0.0220031738281 -0.369995117188,-0.0429992675781 -0.556976318359,-0.0599975585937 c -0.592010498047,-0.0530090332031 -1.18801879883,-0.0899963378906 -1.79602050781,-0.0899963378907 c -0.605987548828,0.0 -1.20300292969,0.0369873046875 -1.79598999023,0.0899963378907 c -0.186004638672,0.0169982910156 -0.371002197266,0.0379943847656 -0.555999755859,0.0599975585937 c -0.423004150391,0.0499877929688 -0.842010498047,0.114990234375 -1.25601196289,0.190979003906 c -0.18798828125,0.0350036621094 -0.377990722656,0.06201171875 -0.563995361328,0.101013183594 c -0.483001708984,0.10400390625 -0.959991455078,0.22900390625 -1.42999267578,0.368011474609 c -0.321990966797,0.093994140625 -0.638000488281,0.201995849609 -0.953002929688,0.311981201172 c -0.162994384766,0.0570068359375 -0.324005126953,0.115997314453 -0.484985351562,0.177001953125 c -1.18099975586,0.445007324219 -2.30599975586,0.997009277344 -3.36801147461,1.64700317383 c -0.00201416015625,0.00100708007812 -0.00399780273438,0.00201416015625 -0.0060119628907,0.0029907226562 c -5.74099731445,3.51400756836 -9.58499145508,9.82501220703 -9.58599853516,17.0500183105 c 0,0.0 0,0.00100708007812 0,0.00100708007813 c 0,0.0059814453125 0.00100708007812,0.0130004882812 0.0010070800781,0.0199890136719 c 0.0,0.466003417969 0.0169982910156,0.928009033203 0.0490112304688,1.38598632812 c 0.0050048828125,0.0690002441406 0.0159912109375,0.136016845703 0.02099609375,0.206024169922 c 0.031982421875,0.401000976562 0.0719909667969,0.799987792969 0.127990722656,1.19400024414 c 0.00201416015625,0.0189819335938 0.00701904296875,0.0369873046875 0.010009765625,0.0569763183594 c 0.888000488281,6.17202758789 4.59799194336,11.4250183105 9.7799987793,14.4309997559 c 0.0,0.0 2.00198364258,-3.458984375 2.00198364258,-3.458984375 c -2.58599853516,-1.5 -4.708984375,-3.70401000977 -6.11697387695,-6.34399414063 c 0.0,0.0 0.0169982910156,-0.0180053710938 0.0169982910156,-0.0180053710938 c -0.890014648438,-1.67098999023 -1.50601196289,-3.5110168457 -1.76000976562,-5.46499633789 c -0.00698852539062,-0.0500183105469 -0.010009765625,-0.102020263672 -0.0159912109375,-0.152008056641 c -0.0330200195312,-0.273010253906 -0.0610046386719,-0.545989990234 -0.0800170898437,-0.821990966797 c -0.0220031738281,-0.343017578125 -0.0350036621094,-0.68701171875 -0.0350036621094,-1.03500366211 c 0,-6.53701782227 3.92599487305,-12.1480102539 9.54299926758,-14.6310119629 c 0.157012939453,-0.0700073242188 0.313995361328,-0.135986328125 0.472015380859,-0.199981689453 c 0.373992919922,-0.151000976562 0.751983642578,-0.294006347656 1.13900756836,-0.417022705078 c 0.108978271484,-0.0350036621094 0.221984863281,-0.0619812011719 0.332000732422,-0.0950012207031 c 0.349975585938,-0.102996826172 0.705993652344,-0.194976806641 1.06597900391,-0.273986816406 c 0.114013671875,-0.0249938964844 0.227996826172,-0.052001953125 0.342010498047,-0.0750122070313 c 0.440002441406,-0.0869750976562 0.885986328125,-0.154998779297 1.33700561523,-0.203979492188 c 0.10400390625,-0.0120239257812 0.209991455078,-0.02001953125 0.315002441406,-0.0299987792969 c 0.47998046875,-0.0429992675781 0.963989257812,-0.072998046875 1.45397949219,-0.072998046875 c 0.492004394531,0.0 0.975006103516,0.0299987792969 1.45401000977,0.072998046875 c 0.105987548828,0.00997924804688 0.212005615234,0.0179748535156 0.316986083984,0.0299987792969 c 0.450012207031,0.0489807128906 0.89501953125,0.117004394531 1.33502197266,0.203002929688 c 0.115997314453,0.0239868164062 0.22998046875,0.0509948730469 0.345001220703,0.0769958496094 c 0.358001708984,0.0780029296875 0.710998535156,0.169982910156 1.06097412109,0.272003173828 c 0.111022949219,0.0329895019531 0.226013183594,0.0609741210938 0.336029052734,0.0969848632813 c 0.385986328125,0.123016357422 0.761993408203,0.265014648438 1.13497924805,0.415008544922 c 0.160003662109,0.0650024414062 0.319000244141,0.131988525391 0.477020263672,0.201995849609 c 5.61599731445,2.48400878906 9.53997802734,8.09399414062 9.53997802734,14.6310119629 c 0,0.346984863281 -0.0130004882812,0.690979003906 -0.0350036621094,1.03399658203 c -0.0179748535156,0.274993896484 -0.0469970703125,0.548004150391 -0.0789794921875,0.819000244141 c -0.00601196289062,0.052001953125 -0.010009765625,0.10498046875 -0.0160217285156,0.154998779297 c -0.252990722656,1.95498657227 -0.871002197266,3.79400634766 -1.75997924805,5.46499633789 c 0.0,0.0 0.0169982910156,0.0180053710938 0.0169982910156,0.0180053710938 c -1.40802001953,2.63998413086 -3.53100585938,4.84399414062 -6.11700439453,6.34399414063 c 0.0,0.0 2.00198364258,3.458984375 2.00198364258,3.458984375 c 5.18402099609,-3.00698852539 8.89501953125,-8.26300048828 9.78100585938,-14.4379882813 c 0.00201416015625,-0.0169982910156 0.00601196289062,-0.0320129394531 0.0079956054688,-0.0490112304688 c 0.0570068359375,-0.39697265625 0.0970153808594,-0.798980712891 0.129028320312,-1.20300292969 Z"
-                        android:fillColor="#FFFFFFFF"
-                        android:fillAlpha="1" />
-                </group>
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors.xml b/packages/SystemUI/res/drawable/ic_invert_colors.xml
new file mode 100644
index 0000000..f7a86a4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_invert_colors.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <group
+        android:translateX="-0.61">
+        <path
+            android:pathData="M17.44,7.71L12.7,2.97a0.996,0.996 0,0 0,-1.41 0L6.56,7.71c-3,3 -3.4,7.89 -0.62,11.1 1.6,1.85 3.83,2.77 6.06,2.77s4.46,-0.92 6.06,-2.77c2.78,-3.21 2.38,-8.1 -0.62,-11.1zM12,19.59c-1.6,0 -3.11,-0.62 -4.24,-1.76C6.62,16.69 6,15.19 6,13.59s0.62,-3.11 1.76,-4.24L12,5.1v14.49z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
deleted file mode 100644
index 49ee48b..0000000
--- a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:alpha="1.0"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="icon"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="icon_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="0"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="ink_drop"
-                android:translateY="-6.8" >
-                <path
-                    android:name="outer_drop"
-                    android:pathData="M 35.3000030518,15.8999938965 c 0.0,0.0 -11.3000030518,-11.3999938965 -11.3000030518,-11.3999938965 c 0,0.0 -11.3000030518,11.3999938965 -11.3000030518,11.3999938965 c -6.19999694824,6.20001220703 -6.19999694824,16.4000091553 0.0,22.6000061035 c 3.10000610352,3.10000610352 7.19999694824,4.69999694824 11.3000030518,4.69999694824 c 4.10000610352,0.0 8.19999694824,-1.59999084473 11.3000030518,-4.69999694824 c 6.30000305176,-6.30000305176 6.30000305176,-16.3999938965 0.0,-22.6000061035 Z M 24,39.1999969482 c 0,0.0 0,0.0 0,0.0 c -3.19999694824,0.0 -6.19999694824,-1.19999694824 -8.5,-3.5 c -2.30000305176,-2.29998779297 -3.5,-5.30000305176 -3.5,-8.5 c 0,-3.19999694824 1.19999694824,-6.19999694824 3.5,-8.5 c 0.0,0.0 8.5,-8.5 8.5,-8.5 c 0,0.0 0,29.0 0,29.0 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
deleted file mode 100644
index 169cc71..0000000
--- a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="icon"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="icon_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="1"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="ink_drop"
-                android:translateY="-6.8" >
-                <path
-                    android:name="outer_drop"
-                    android:pathData="M 35.3000030518,15.8999938965 c 0.0,0.0 -11.3000030518,-11.3999938965 -11.3000030518,-11.3999938965 c 0,0.0 -11.3000030518,11.3999938965 -11.3000030518,11.3999938965 c -6.19999694824,6.20001220703 -6.19999694824,16.4000091553 0.0,22.6000061035 c 3.10000610352,3.10000610352 7.19999694824,4.69999694824 11.3000030518,4.69999694824 c 4.10000610352,0.0 8.19999694824,-1.59999084473 11.3000030518,-4.69999694824 c 6.30000305176,-6.30000305176 6.30000305176,-16.3999938965 0.0,-22.6000061035 Z M 24,39.1999969482 c 0,0.0 0,0.0 0,0.0 c -3.19999694824,0.0 -6.19999694824,-1.19999694824 -8.5,-3.5 c -2.30000305176,-2.29998779297 -3.5,-5.30000305176 -3.5,-8.5 c 0,-3.19999694824 1.19999694824,-6.19999694824 3.5,-8.5 c 0.0,0.0 8.5,-8.5 8.5,-8.5 c 0,0.0 0,29.0 0,29.0 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_mode_edit.xml b/packages/SystemUI/res/drawable/ic_mode_edit.xml
index f32da59..2ad3119 100644
--- a/packages/SystemUI/res/drawable/ic_mode_edit.xml
+++ b/packages/SystemUI/res/drawable/ic_mode_edit.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -21,5 +21,5 @@
         android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.81,9.94l-3.75,-3.75L3.0,17.25zM20.71,7.04c0.39,-0.3 0.39,-1.02 0.0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+        android:pathData="M3,18.08v2.42c0,0.28 0.22,0.5 0.5,0.5h2.42c0.53,0 1.04,-0.21 1.41,-0.59L17.81,9.94l-3.75,-3.75L3.59,16.66c-0.38,0.38 -0.59,0.89 -0.59,1.42zM20.71,7.04a0.996,0.996 0,0 0,0 -1.41l-2.34,-2.34a0.996,0.996 0,0 0,-1.41 0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
index 8a3e975..3eb81f8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,13 +14,12 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
-
+    android:width="64dp"
+    android:height="64dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal" >
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M14.0,24.0l-4.0,-4.0l-4.0,4.0l4.0,4.0L14.0,24.0zM35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6zM38.0,20.0l-4.0,4.0l4.0,4.0l4.0,-4.0L38.0,20.0z"/>
+        android:pathData="M13.51,12l3.75,-3.74c0.41,-0.41 0.41,-1.07 0,-1.48l-4.47,-4.47 -0.03,-0.03a1.046,1.046 0,0 0,-1.76 0.76v6.44L6.95,5.43c-0.41,-0.41 -1.06,-0.41 -1.47,0s-0.41,1.06 0,1.47l5.09,5.1 -5.09,5.09c-0.41,0.41 -0.41,1.06 0,1.47s1.06,0.41 1.47,0L11,14.51v6.45a1.04,1.04 0,0 0,1.75 0.76l0.05,-0.05 4.46,-4.46c0.41,-0.41 0.41,-1.07 0,-1.48L13.51,12zM12.99,9.67v-4.3l2.15,2.15 -2.15,2.15zM12.99,18.62v-4.3l2.15,2.15 -2.15,2.15zM6.06,13.06c-0.59,0.59 -1.54,0.59 -2.12,0a1.49,1.49 0,0 1,0 -2.12,1.49 1.49,0 0,1 2.12,0c0.59,0.59 0.59,1.53 0,2.12zM20.06,10.94c0.59,0.59 0.59,1.54 0,2.12 -0.59,0.59 -1.54,0.59 -2.12,0a1.49,1.49 0,0 1,0 -2.12,1.49 1.49,0 0,1 2.12,0z"
+        android:fillColor="#FFFFFFFF" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
index 1dadc05..fbd92de 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,13 +14,12 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
-
+    android:width="64dp"
+    android:height="64dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal" >
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M28.5,24.0l4.6,4.6c0.6,-1.4 0.9,-3.0 0.9,-4.7c0.0,-1.6 -0.3,-3.2 -0.9,-4.6L28.5,24.0zM39.1,13.4L36.5,16.0c1.3,2.4 2.0,5.1 2.0,8.0s-0.7,5.6 -2.0,8.0l2.4,2.4c1.9,-3.1 3.1,-6.7 3.1,-10.6C42.0,20.0 40.9,16.5 39.1,13.4zM31.4,15.4L20.0,4.0l-2.0,0.0l0.0,15.2L8.8,10.0L6.0,12.8L17.2,24.0L6.0,35.2L8.8,38.0l9.2,-9.2L18.0,44.0l2.0,0.0l11.4,-11.4L22.8,24.0L31.4,15.4zM22.0,11.7l3.8,3.8L22.0,19.2L22.0,11.7zM25.8,32.6L22.0,36.3l0.0,-7.5L25.8,32.6z"/>
+        android:pathData="M14.95,11.3l1.62,-1.61C16.84,10.41 17,11.18 17,12s-0.16,1.61 -0.44,2.33l-1.61,-1.61C14.56,12.33 14.56,11.69 14.95,11.3zM18.69,7.54c-0.26,0.26 -0.32,0.65 -0.17,0.98c0.47,1.07 0.72,2.24 0.72,3.47c0,1.24 -0.26,2.43 -0.73,3.49c-0.14,0.32 -0.09,0.69 0.16,0.94c0.4,0.4 1.09,0.29 1.34,-0.23c0.63,-1.3 0.98,-2.76 0.98,-4.3c-0.01,-1.46 -0.33,-2.86 -0.91,-4.12C19.84,7.23 19.12,7.11 18.69,7.54zM15.26,15.74c0.41,0.41 0.41,1.07 0,1.48l-4.51,4.51C10.57,21.89 10.32,22 10.04,22C9.47,22 9,21.53 9,20.96v-6.45l-4.05,4.05c-0.41,0.41 -1.06,0.41 -1.47,0s-0.41,-1.06 0,-1.47L8.57,12L3.48,6.9c-0.41,-0.41 -0.41,-1.06 0,-1.47s1.06,-0.41 1.47,0L9,9.49V3.04C9,2.47 9.47,2 10.04,2c0.28,0 0.53,0.11 0.72,0.29l4.5,4.5c0.41,0.41 0.41,1.07 0,1.48L11.51,12L15.26,15.74zM13.14,7.53l-2.15,-2.15v4.3C10.99,9.68 13.14,7.53 13.14,7.53zM13.14,16.47l-2.15,-2.15v4.3C10.99,18.62 13.14,16.47 13.14,16.47z"
+        android:fillColor="#FFFFFFFF" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
index 33a4047..e6d6f2c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -16,12 +16,12 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="56dp"
         android:height="56dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
         android:alpha="0.14"
         android:tint="?android:attr/colorForeground">
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6z"/>
+        android:pathData="M13.5,12l3.8,-3.7c0.4,-0.4 0.4,-1.1 0,-1.5l-4.5,-4.5c-0.4,-0.4 -1.1,-0.4 -1.5,0.1C11.1,2.5 11,2.8 11,3v6.4L6.9,5.4C6.5,5 5.9,5 5.5,5.4s-0.4,1.1 0,1.5l5.1,5.1l-5.1,5.1c-0.4,0.4 -0.4,1.1 0,1.5s1.1,0.4 1.5,0l4.1,-4V21c0,0.6 0.5,1 1,1c0.3,0 0.5,-0.1 0.7,-0.3l0.1,0l4.5,-4.5c0.4,-0.4 0.4,-1.1 0,-1.5L13.5,12zM13,9.7V5.4l2.1,2.2L13,9.7zM13,18.6v-4.3l2.1,2.2L13,18.6z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
deleted file mode 100644
index 3148a2c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
-
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M26.0,11.8l3.8,3.8l-3.2,3.2l2.8,2.8l6.0,-6.0L24.0,4.2l-2.0,0.0l0.0,10.1l4.0,4.0L26.0,11.8zM10.8,8.2L8.0,11.0l13.2,13.2L10.0,35.3l2.8,2.8L22.0,29.0l0.0,15.2l2.0,0.0l8.6,-8.6l4.6,4.6l2.8,-2.8L10.8,8.2zM26.0,36.5L26.0,29.0l3.8,3.8L26.0,36.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
index 2e9e741..8cc6caa 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,13 +14,12 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
-
+    android:width="64dp"
+    android:height="64dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6z"/>
+        android:pathData="M13.5,12l3.8,-3.7c0.4,-0.4 0.4,-1.1 0,-1.5l-4.5,-4.5c-0.4,-0.4 -1.1,-0.4 -1.5,0.1C11.1,2.5 11,2.8 11,3v6.4L6.9,5.4C6.5,5 5.9,5 5.5,5.4s-0.4,1.1 0,1.5l5.1,5.1l-5.1,5.1c-0.4,0.4 -0.4,1.1 0,1.5s1.1,0.4 1.5,0l4.1,-4V21c0,0.6 0.5,1 1,1c0.3,0 0.5,-0.1 0.7,-0.3l0.1,0l4.5,-4.5c0.4,-0.4 0.4,-1.1 0,-1.5L13.5,12zM13,9.7V5.4l2.1,2.2L13,9.7zM13,18.6v-4.3l2.1,2.2L13,18.6z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
index b7fe5ab..aaebc77 100644
--- a/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2014 The Android Open Source Project
+     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.
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
index fc831f4..ffde286 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -23,5 +23,5 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/>
+        android:pathData="M1,18v2c0,0.55 0.45,1 1,1h2c0,-1.66 -1.34,-3 -3,-3zM0.97,15.06c-0.01,0.51 0.35,0.93 0.85,1.02 2.08,0.36 3.74,2 4.1,4.08 0.09,0.48 0.5,0.84 0.99,0.84 0.61,0 1.09,-0.54 1,-1.14a6.996,6.996 0,0 0,-5.8 -5.78c-0.59,-0.09 -1.12,0.38 -1.14,0.98zM0.97,11.03c-0.01,0.52 0.37,0.96 0.88,1.01 4.26,0.43 7.68,3.82 8.1,8.08 0.05,0.5 0.48,0.88 0.99,0.88 0.59,0 1.06,-0.51 1,-1.1 -0.52,-5.21 -4.66,-9.34 -9.87,-9.85 -0.57,-0.05 -1.08,0.4 -1.1,0.98zM21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
index 06a0886..9e57577 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,12 +14,11 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-
+    android:width="64dp"
+    android:height="64dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/>
+        android:pathData="M1,18v2c0,0.55 0.45,1 1,1h2c0,-1.66 -1.34,-3 -3,-3zM0.97,15.06c-0.01,0.51 0.35,0.93 0.85,1.02 2.08,0.36 3.74,2 4.1,4.08 0.09,0.48 0.5,0.84 0.99,0.84 0.61,0 1.09,-0.54 1,-1.14a6.996,6.996 0,0 0,-5.8 -5.78c-0.59,-0.09 -1.12,0.38 -1.14,0.98zM0.97,11.03c-0.01,0.52 0.37,0.96 0.88,1.01 4.26,0.43 7.68,3.82 8.1,8.08 0.05,0.5 0.48,0.88 0.99,0.88 0.59,0 1.06,-0.51 1,-1.1 -0.52,-5.21 -4.66,-9.34 -9.87,-9.85 -0.57,-0.05 -1.08,0.4 -1.1,0.98zM21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2z"
+        android:fillColor="#FFFFFFFF" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
index 794eb9e..3dda87c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -16,10 +16,10 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="64dp"
         android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z"/>
+        android:pathData="M1,18v2c0,0.55 0.45,1 1,1h2c0,-1.66 -1.34,-3 -3,-3zM0.97,15.06c-0.01,0.51 0.35,0.93 0.85,1.02 2.08,0.36 3.74,2 4.1,4.08 0.09,0.48 0.5,0.84 0.99,0.84 0.61,0 1.09,-0.54 1,-1.14a6.996,6.996 0,0 0,-5.8 -5.78c-0.59,-0.09 -1.12,0.38 -1.14,0.98zM19,7L5,7v1.63c3.96,1.28 7.09,4.41 8.37,8.37L19,17L19,7zM0.97,11.03c-0.01,0.52 0.37,0.96 0.88,1.01 4.26,0.43 7.68,3.82 8.1,8.08 0.05,0.5 0.48,0.88 0.99,0.88 0.59,0 1.06,-0.51 1,-1.1 -0.52,-5.21 -4.66,-9.34 -9.87,-9.85 -0.57,-0.05 -1.08,0.4 -1.1,0.98zM21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_detail_empty.xml
new file mode 100644
index 0000000..d71018b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_detail_empty.xml
@@ -0,0 +1,26 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="56dp"
+    android:height="56dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:alpha="0.14"
+    android:tint="?android:attr/colorForeground">
+    <path
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16,13L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
deleted file mode 100644
index 9168dbc..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<!--
-Copyright (C) 2015 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="64dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0"
-    android:width="64dp" >
-
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.8,11.1L17.0,11.1l0.0,2.0l-1.2,0.0l4.5,4.5c1.1,-1.6 1.7,-3.5 1.7,-5.5c0.0,-5.5 -4.5,-10.0 -10.0,-10.0c-2.0,0.0 -3.9,0.6 -5.5,1.7L13.8,11.1z" />
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.0,13.1L7.0,13.1l0.0,-2.0l4.0,0.0L4.9,5.0C3.1,6.8 2.0,9.3 2.0,12.1c0.0,5.5 4.5,10.0 10.0,10.0c2.8,0.0 5.3,-1.1 7.1,-2.9L13.0,13.1z" />
-
-    <group
-        android:pivotX="12.0"
-        android:pivotY="12.0"
-        android:rotation="45.0"
-        android:translateX="0.5"
-        android:translateY="0.5" >
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M-2.8,11.8l28.3,0.0l0.0,2.0l-28.3,0.0z" />
-    </group>
-
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
index f4c20a9..233b9b9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2015 The Android Open Source Project
+    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.
@@ -16,9 +16,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="64dp"
         android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/>
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16,13L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"
+        android:fillColor="#FFFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
index fb26c09..5012aa4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2015 The Android Open Source Project
+    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.
@@ -18,12 +18,7 @@
         android:height="64dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
-
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0s10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,20.5c-4.7,0.0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12.0,3.5s8.5,3.8 8.5,8.5S16.7,20.5 12.0,20.5z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,3.3 2.7,6.0 6.0,6.0s6.0,-2.7 6.0,-6.0C18.0,8.7 15.4,6.0 12.0,6.0zM15.0,13.0L9.0,13.0l0.0,-2.0l6.0,0.0L15.0,13.0z"/>
-
+        android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10 10,-4.5 10,-10S17.5,2 12,2zM12,20.5c-4.7,0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12,3.5s8.5,3.8 8.5,8.5 -3.8,8.5 -8.5,8.5zM12,6c-3.3,0 -6,2.7 -6,6s2.7,6 6,6 6,-2.7 6,-6 -2.6,-6 -6,-6zM14,13h-4c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h4c0.55,0 1,0.45 1,1s-0.45,1 -1,1z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
deleted file mode 100644
index aaca663..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-    Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="64dp"
-    android:height="64dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-
-    <path
-        android:fillColor="#FFF"
-        android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
-
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
index aaca663..8801f5d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -16,11 +16,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:width="64dp"
     android:height="64dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFF"
-        android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
-
-</vector>
+        android:pathData="M13,12c0,-3.57 2.2,-6.62 5.31,-7.87 0.89,-0.36 0.75,-1.69 -0.19,-1.9 -1.1,-0.24 -2.27,-0.3 -3.48,-0.14 -4.51,0.6 -8.12,4.31 -8.59,8.83C5.43,16.93 10.12,22 16,22c0.73,0 1.43,-0.08 2.12,-0.23 0.95,-0.21 1.1,-1.53 0.2,-1.9A8.471,8.471 0,0 1,13 12z"
+        android:fillColor="#FFF"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index e6f9292..7cbc26f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,15 +14,19 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25.50"
+    android:viewportHeight="25.50">
+    <group
+        android:translateX="0.77"
+        android:translateY="0.23" >
+        <path
+            android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+            android:fillAlpha="0.3"
+            android:fillColor="#FFFFFF"/>
+        <path
+            android:pathData="M22.71,15.67l-1.83,1.83l1.83,1.83c0.38,0.38 0.38,1 0,1.38v0c-0.38,0.38 -1,0.39 -1.38,0l-1.83,-1.83l-1.83,1.83c-0.38,0.38 -1,0.38 -1.38,0l-0.01,-0.01c-0.38,-0.38 -0.38,-1 0,-1.38l1.83,-1.83l-1.82,-1.82c-0.38,-0.38 -0.38,-1 0,-1.38l0.01,-0.01c0.38,-0.38 1,-0.38 1.38,0l1.82,1.82l1.82,-1.82c0.38,-0.38 1,-0.38 1.38,0l0,0C23.09,14.67 23.09,15.29 22.71,15.67z"
+            android:fillColor="#FFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index d423ccb..675dfc9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,18 +14,19 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25.50"
+    android:viewportHeight="25.50">
+    <group
+        android:translateX="0.77"
+        android:translateY="0.23" >
+        <path
+            android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+            android:fillAlpha="0.3"
+            android:fillColor="#FFFFFF"/>
+        <path
+            android:pathData="M14,20.13l-1.18,1.47c-0.43,0.53 -1.23,0.53 -1.66,0l-5.1,-6.35C7.65,13.85 9.72,13 12,13c0.69,0 1.36,0.08 2,0.23V20.13zM22.71,14.29L22.71,14.29c-0.38,-0.38 -1,-0.39 -1.38,0l-1.82,1.82l-1.82,-1.82c-0.38,-0.38 -1,-0.38 -1.38,0l-0.01,0.01c-0.38,0.38 -0.38,1 0,1.38l1.82,1.82l-1.83,1.83c-0.38,0.38 -0.38,1 0,1.38l0.01,0.01c0.38,0.38 1,0.38 1.38,0l1.83,-1.83l1.83,1.83c0.38,0.38 1,0.38 1.38,0v0c0.38,-0.38 0.38,-1 0,-1.38l-1.83,-1.83l1.83,-1.83C23.09,15.29 23.09,14.67 22.71,14.29z"
+            android:fillColor="#FFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index 1982130..c9a7eb8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,18 +14,19 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25.50"
+    android:viewportHeight="25.50">
+    <group
+        android:translateX="0.77"
+        android:translateY="0.23" >
+        <path
+            android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+            android:fillAlpha="0.3"
+            android:fillColor="#FFFFFF"/>
+        <path
+            android:pathData="M14,20.13l-1.18,1.47c-0.43,0.53 -1.23,0.53 -1.66,0l-6.98,-8.7C6.28,11.1 9.01,10 12,10c2.45,0 4.72,0.74 6.62,2H14V20.13zM22.71,14.29L22.71,14.29c-0.38,-0.38 -1,-0.39 -1.38,0l-1.82,1.82l-1.82,-1.82c-0.38,-0.38 -1,-0.38 -1.38,0l-0.01,0.01c-0.38,0.38 -0.38,1 0,1.38l1.82,1.82l-1.83,1.83c-0.38,0.38 -0.38,1 0,1.38l0.01,0.01c0.38,0.38 1,0.38 1.38,0l1.83,-1.83l1.83,1.83c0.38,0.38 1,0.38 1.38,0v0c0.38,-0.38 0.38,-1 0,-1.38l-1.83,-1.83l1.83,-1.83C23.09,15.29 23.09,14.67 22.71,14.29z"
+            android:fillColor="#FFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index b350111..a6facae 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,18 +14,19 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25.50"
+    android:viewportHeight="25.50">
+    <group
+        android:translateX="0.77"
+        android:translateY="0.23" >
+        <path
+            android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+            android:fillAlpha="0.3"
+            android:fillColor="#FFFFFF"/>
+        <path
+            android:pathData="M14,20.13l-1.18,1.47c-0.43,0.53 -1.23,0.53 -1.66,0L2.93,11.35C5.37,9.26 8.54,8 12,8c3.46,0 6.62,1.26 9.07,3.34L20.54,12H14V20.13zM22.71,14.29L22.71,14.29c-0.38,-0.38 -1,-0.39 -1.38,0l-1.82,1.82l-1.82,-1.82c-0.38,-0.38 -1,-0.38 -1.38,0l-0.01,0.01c-0.38,0.38 -0.38,1 0,1.38l1.82,1.82l-1.83,1.83c-0.38,0.38 -0.38,1 0,1.38l0.01,0.01c0.38,0.38 1,0.38 1.38,0l1.83,-1.83l1.83,1.83c0.38,0.38 1,0.38 1.38,0v0c0.38,-0.38 0.38,-1 0,-1.38l-1.83,-1.83l1.83,-1.83C23.09,15.29 23.09,14.67 22.71,14.29z"
+            android:fillColor="#FFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index 136a004..2eae8f5 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,14 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="#FFFFFF"/>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25.50"
+    android:viewportHeight="25.50">
+    <group
+        android:translateX="0.77"
+        android:translateY="0.23" >
+        <path
+            android:pathData="M22.71,15.67l-1.83,1.83l1.83,1.83c0.38,0.38 0.38,1 0,1.38v0c-0.38,0.38 -1,0.39 -1.38,0l-1.83,-1.83l-1.83,1.83c-0.38,0.38 -1,0.38 -1.38,0l-0.01,-0.01c-0.38,-0.38 -0.38,-1 0,-1.38l1.83,-1.83l-1.82,-1.82c-0.38,-0.38 -0.38,-1 0,-1.38l0.01,-0.01c0.38,-0.38 1,-0.38 1.38,0l1.82,1.82l1.82,-1.82c0.38,-0.38 1,-0.38 1.38,0l0,0C23.09,14.67 23.09,15.29 22.71,15.67zM14,12h6.54l3.12,-3.89c0.39,-0.48 0.28,-1.19 -0.23,-1.54C21.66,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+            android:fillColor="#FFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
index 7993c80..95345b8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,14 +14,17 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="56dp"
-        android:height="56dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:alpha="0.14"
-        android:tint="?android:attr/colorForeground">
-
-    <path
-        android:pathData="M24.0,4.0C15.0,4.0 6.7,7.0 0.0,12.0l24.0,32.0l24.0,-32.0C41.3,7.0 33.0,4.0 24.0,4.0z"
-        android:fillColor="#FFFFFF" />
+    android:width="56dp"
+    android:height="56dp"
+    android:viewportWidth="25.0"
+    android:viewportHeight="23.5"
+    android:alpha="0.14"
+    android:tint="?android:attr/colorForeground" >
+    <group
+        android:translateX="0.51"
+        android:translateY="-1.1">
+        <path
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#FFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
index 30c10dc..ea02ba7 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,14 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="32.0dp"
+    android:width="32dp"
     android:height="29.5dp"
-    android:viewportWidth="26.0"
-    android:viewportHeight="24.0">
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.6">
     <group
-        android:translateY="2">
+        android:translateX="0.8"
+        android:translateY="1.1">
         <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#FFFFFFFF"/>
     </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
index 2dcdb71..cb87cae 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -14,29 +14,19 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="26.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.0,8.5
-        c0.85,0.0 1.6,0.23 2.3,0.62l2.24,-2.79
-        C25.1,5.96 20.26,2.0 13.0,2.0
-        S0.9,5.9 0.42,6.32
-        l12.57,15.6 4.21,-5.17
-        c-0.76,-0.87 -1.22,-2.0 -1.22,-3.25
-        c0.0,-2.76 2.24,-5.0 5.0,-5.0z"
-        android:fillAlpha=".3"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.0,10.0
-        c-1.93,0.0 -3.5,1.57 -3.5,3.5l1.75,0.0
-        c0.0,-0.9 0.78,-1.75 1.75,-1.75s1.7,0.78 1.75,1.75
-        c0.0,0.48 -0.2,0.92 -0.51,1.24l-1.09,1.1
-        c-0.6,0.63 -1.02,1.51 -1.02,2.47l0.0,0.44l1.75,0.0
-        c0.0,-1.3 0.39,-1.84 1.03,-2.47l0.78,-0.8
-        c0.5,-0.5 0.82,-1.2 0.82,-1.97
-        C24.5,11.57 22.93,10.0 21.0,10.0z
-        m-0.95,11.95l1.9,0.0l0.0,-1.9l-1.9,0.0l0.0,1.9z"/>
+    android:width="26dp"
+    android:height="24dp"
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.7">
+    <group
+        android:translateX="0.82"
+        android:translateY="-1">
+        <path
+            android:pathData="M18.9,20.85c0,-0.61 0.49,-1.1 1.1,-1.1 0.61,0 1.1,0.49 1.1,1.1 0,0.61 -0.49,1.1 -1.1,1.1 -0.61,0 -1.1,-0.49 -1.1,-1.1zM20,10c-1.53,0 -2.84,0.99 -3.31,2.36 -0.19,0.56 0.23,1.14 0.81,1.14 0.36,0 0.72,-0.21 0.84,-0.55 0.23,-0.7 0.89,-1.2 1.66,-1.2 0.97,0 1.75,0.78 1.75,1.75 0,0.48 -0.2,0.92 -0.51,1.24l-1.09,1.1c-0.69,0.69 -0.92,1.38 -0.99,2.2 -0.04,0.51 0.36,0.96 0.88,0.96 0.44,0 0.83,-0.33 0.87,-0.77 0.07,-0.79 0.31,-1.27 1,-1.95l0.78,-0.8c0.5,-0.5 0.82,-1.2 0.82,-1.97C23.5,11.57 21.93,10 20,10z"
+            android:fillColor="#FFFFFFFF"/>
+        <path
+            android:pathData="M14.73,12.88c0,-2.7 2.19,-4.88 4.88,-4.88 1.22,0 2.32,0.46 3.18,1.2l0.88,-1.09c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0l3.88,-4.82a4.862,4.862 0,0 1,-1.97 -3.9z"
+            android:fillAlpha="0.3"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
index 1bc7438..53e4efc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,11 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="32.0dp"
+    android:height="29.5dp"
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.6">
+    <group
+        android:translateX="0.8"
+        android:translateY="-0.9">
+        <path
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#4DFFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
index 5856115..8294183 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,14 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.100000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
+    android:width="32dp"
+    android:height="29.5dp"
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.6">
+    <group
+        android:translateX="0.8"
+        android:translateY="-0.9">
+        <path
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#4DFFFFFF"/>
+        <path
+            android:pathData="M12.82,21.6l5.11,-6.36A8.942,8.942 0,0 0,12 13c-2.28,0 -4.35,0.85 -5.94,2.25l5.1,6.35c0.43,0.53 1.23,0.53 1.66,0z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
index 4a5e1f8..3d59cf2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,14 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.000000,22.000000l7.600000,-9.400000C20.299999,12.400000 17.400000,10.000000 13.000000,10.000000s-7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="32dp"
+    android:height="29.5dp"
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.6">
+    <group
+        android:translateX="0.8"
+        android:translateY="-0.9">
+        <path
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#4DFFFFFF"/>
+        <path
+            android:pathData="M12.82,21.6l6.99,-8.7C17.71,11.1 14.99,10 12,10c-2.99,0 -5.72,1.1 -7.82,2.91l6.98,8.7c0.43,0.52 1.23,0.52 1.66,-0.01z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
index 965442d..21313b8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,14 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.000000,22.000000l9.200000,-11.400000c-0.400000,-0.300000 -3.900000,-3.200000 -9.200000,-3.200000s-8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="32dp"
+    android:height="29.5dp"
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.6">
+    <group
+        android:translateX="0.8"
+        android:translateY="-0.9">
+        <path
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#4DFFFFFF"/>
+        <path
+            android:pathData="M12.82,21.6l8.25,-10.26A13.961,13.961 0,0 0,12 8c-3.46,0 -6.63,1.26 -9.07,3.35l8.23,10.26c0.43,0.52 1.23,0.52 1.66,-0.01z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
index b29d3f9..fd763ff 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -14,11 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="32dp"
+    android:height="29.5dp"
+    android:viewportWidth="25.6"
+    android:viewportHeight="23.6">
+    <group
+        android:translateX="0.8"
+        android:translateY="-0.9">
+        <path
+            android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings.xml b/packages/SystemUI/res/drawable/ic_settings.xml
index 9c78742..6d24c7e 100644
--- a/packages/SystemUI/res/drawable/ic_settings.xml
+++ b/packages/SystemUI/res/drawable/ic_settings.xml
@@ -1,4 +1,4 @@
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- 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"+
@@ -13,14 +13,11 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-android:width="24dp"
-android:height="24dp" android:viewportWidth="24.0"
-          android:viewportHeight="24.0">
-
-
-<path
-     android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
-     android:fillColor="#ffffffff"
-     />
-
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:pathData="M21.4,14.2l-1.94,-1.45c0.03,-0.25 0.04,-0.5 0.04,-0.76s-0.01,-0.51 -0.04,-0.76L21.4,9.8c0.42,-0.31 0.52,-0.94 0.24,-1.41l-1.6,-2.76c-0.28,-0.48 -0.88,-0.7 -1.36,-0.5l-2.14,0.91c-0.48,-0.37 -1.01,-0.68 -1.57,-0.92l-0.27,-2.2c-0.06,-0.52 -0.56,-0.92 -1.11,-0.92h-3.18c-0.55,0 -1.05,0.4 -1.11,0.92l-0.26,2.19c-0.57,0.24 -1.1,0.55 -1.58,0.92l-2.14,-0.91c-0.48,-0.2 -1.08,0.02 -1.36,0.5l-1.6,2.76c-0.28,0.48 -0.18,1.1 0.24,1.42l1.94,1.45c-0.03,0.24 -0.04,0.49 -0.04,0.75s0.01,0.51 0.04,0.76L2.6,14.2c-0.42,0.31 -0.52,0.94 -0.24,1.41l1.6,2.76c0.28,0.48 0.88,0.7 1.36,0.5l2.14,-0.91c0.48,0.37 1.01,0.68 1.57,0.92l0.27,2.19c0.06,0.53 0.56,0.93 1.11,0.93h3.18c0.55,0 1.04,-0.4 1.11,-0.92l0.27,-2.19c0.56,-0.24 1.09,-0.55 1.57,-0.92l2.14,0.91c0.48,0.2 1.08,-0.02 1.36,-0.5l1.6,-2.76c0.28,-0.48 0.18,-1.1 -0.24,-1.42zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"
+        android:fillColor="#FFFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings_16dp.xml b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
index c21b60c..e3ed229 100644
--- a/packages/SystemUI/res/drawable/ic_settings_16dp.xml
+++ b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -19,6 +19,6 @@
     android:viewportWidth="24.0"
     android:viewportHeight="24.0">
     <path
-        android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
-        android:fillColor="#ffffffff" />
+        android:pathData="M21.4,14.2l-1.94,-1.45c0.03,-0.25 0.04,-0.5 0.04,-0.76s-0.01,-0.51 -0.04,-0.76L21.4,9.8c0.42,-0.31 0.52,-0.94 0.24,-1.41l-1.6,-2.76c-0.28,-0.48 -0.88,-0.7 -1.36,-0.5l-2.14,0.91c-0.48,-0.37 -1.01,-0.68 -1.57,-0.92l-0.27,-2.2c-0.06,-0.52 -0.56,-0.92 -1.11,-0.92h-3.18c-0.55,0 -1.05,0.4 -1.11,0.92l-0.26,2.19c-0.57,0.24 -1.1,0.55 -1.58,0.92l-2.14,-0.91c-0.48,-0.2 -1.08,0.02 -1.36,0.5l-1.6,2.76c-0.28,0.48 -0.18,1.1 0.24,1.42l1.94,1.45c-0.03,0.24 -0.04,0.49 -0.04,0.75s0.01,0.51 0.04,0.76L2.6,14.2c-0.42,0.31 -0.52,0.94 -0.24,1.41l1.6,2.76c0.28,0.48 0.88,0.7 1.36,0.5l2.14,-0.91c0.48,0.37 1.01,0.68 1.57,0.92l0.27,2.19c0.06,0.53 0.56,0.93 1.11,0.93h3.18c0.55,0 1.04,-0.4 1.11,-0.92l0.27,-2.19c0.56,-0.24 1.09,-0.55 1.57,-0.92l2.14,0.91c0.48,0.2 1.08,-0.02 1.36,-0.5l1.6,-2.76c0.28,-0.48 0.18,-1.1 -0.24,-1.42zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"
+        android:fillColor="#FFFFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane.xml b/packages/SystemUI/res/drawable/ic_signal_airplane.xml
new file mode 100644
index 0000000..50dd436
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="20.5"
+    android:viewportHeight="20.5">
+    <group
+        android:translateX="0.985"
+        android:translateY="1.10">
+        <path
+            android:pathData="M16.01,9.87l-6.24,-3.9v-4.7C9.77,0.57 9.21,0 8.5,0S7.23,0.57 7.23,1.28v4.7L0.99,9.88c-0.37,0.23 -0.6,0.64 -0.6,1.08v0.41c0,0.29 0.29,0.5 0.55,0.41l6.27,-1.97v4.7l-1.37,1.02c-0.21,0.16 -0.34,0.41 -0.34,0.68v0.57c0,0.15 0.12,0.23 0.27,0.2 1.67,-0.47 1.12,-0.31 2.73,-0.78 1.03,0.3 1.7,0.49 2.72,0.78 0.15,0.03 0.27,-0.06 0.27,-0.2v-0.57c0,-0.27 -0.13,-0.52 -0.34,-0.68l-1.37,-1.02v-4.7l6.27,1.97c0.28,0.09 0.55,-0.12 0.55,-0.41v-0.41c0.01,-0.45 -0.23,-0.87 -0.59,-1.09z"
+            android:fillColor="#FF0"/>
+    </group>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
deleted file mode 100644
index c4ac7ffb..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:alpha="1.0"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_signal_airplane"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="ic_signal_airplane_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="0"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="plane"
-                android:translateX="23.481"
-                android:translateY="15.71151" >
-                <path
-                    android:name="plane_1"
-                    android:pathData="M 18.9439849854,7.98849487305 c 0.0,0.0 0.0,-4.0 0.0,-4.0 c 0.0,0.0 -16.0,-10.0 -16.0,-10.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,-1.70001220703 -1.30000305176,-3.0 -3.0,-3.0 c -1.69999694824,0.0 -3.0,1.29998779297 -3.0,3.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -16.0,10.0 -16.0,10.0 c 0.0,0.0 0.0,4.0 0.0,4.0 c 0.0,0.0 16.0,-5.0 16.0,-5.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -4.0,3.0 -4.0,3.0 c 0.0,0.0 0.0,3.0 0.0,3.0 c 0.0,0.0 7.0,-2.0 7.0,-2.0 c 0.0,0.0 7.0,2.0 7.0,2.0 c 0.0,0.0 0.0,-3.0 0.0,-3.0 c 0.0,0.0 -4.0,-3.0 -4.0,-3.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,0.0 16.0,5.0 16.0,5.0 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
deleted file mode 100644
index b7ac0134..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_signal_airplane"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="ic_signal_airplane_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 37.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 31.5749816895,31.4499664307 31.5749816895,31.4499664307 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="1"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="plane"
-                android:translateX="23.481"
-                android:translateY="18.71151" >
-                <path
-                    android:name="plane_1"
-                    android:pathData="M 18.9439849854,7.98849487305 c 0.0,0.0 0.0,-4.0 0.0,-4.0 c 0.0,0.0 -16.0,-10.0 -16.0,-10.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,-1.70001220703 -1.30000305176,-3.0 -3.0,-3.0 c -1.69999694824,0.0 -3.0,1.29998779297 -3.0,3.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -16.0,10.0 -16.0,10.0 c 0.0,0.0 0.0,4.0 0.0,4.0 c 0.0,0.0 16.0,-5.0 16.0,-5.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -4.0,3.0 -4.0,3.0 c 0.0,0.0 0.0,3.0 0.0,3.0 c 0.0,0.0 7.0,-2.0 7.0,-2.0 c 0.0,0.0 7.0,2.0 7.0,2.0 c 0.0,0.0 0.0,-3.0 0.0,-3.0 c 0.0,0.0 -4.0,-3.0 -4.0,-3.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,0.0 16.0,5.0 16.0,5.0 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight.xml
new file mode 100644
index 0000000..38979a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <group
+        android:translateX="-0.05"
+        android:translateY="0.85" >
+        <path
+            android:pathData="M8.28,2h7.43c0.55,0 1,0.45 1,1v0.96L7.28,3.96L7.28,3c0,-0.55 0.45,-1 1,-1zM14.8,9.76L14.8,21c0,0.55 -0.45,1 -1,1h-3.61c-0.55,0 -1,-0.45 -1,-1L9.19,9.78c-2.2,-1.17 -1.91,-3.76 -1.91,-3.76L7.28,5.7h9.44v0.32s0.26,2.57 -1.92,3.74zM13.38,12.47c0,-0.76 -0.62,-1.38 -1.38,-1.38s-1.38,0.62 -1.38,1.38 0.62,1.38 1.38,1.38 1.38,-0.62 1.38,-1.38z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
deleted file mode 100644
index 35844b7..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:alpha="1.0"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_signal_flashlight"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="ic_signal_flashlight_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 37.8337860107,-39.2849731445 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 8.34049987793,5.6930847168 c 0.0,0.0 0.274993896484,0.29997253418 0.274993896484,0.29997253418 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="0"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="flashlight"
-                android:translateX="25.06235"
-                android:translateY="22.48294" >
-                <path
-                    android:name="light"
-                    android:pathData="M -9.40809631348,-23.6970062256 c 0.0,0.0 18.8699951172,0.0 18.8699951172,0.0 c 0.0,0.0 0.0,3.91700744629 0.0,3.91700744629 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,-3.91700744629 0.0,-3.91700744629 Z M 9.4615020752,-15.6629943848 c 0.0,0.0 0.0,-0.639999389648 0.0,-0.639999389649 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,0.639999389648 0.0,0.639999389649 c 0.0,0.0 -0.581008911133,5.18899536133 3.82598876953,7.52299499512 c 0.0,0.0 0.0,24.4429931641 0.0,24.4429931641 c 0.0,0.0 11.2129974365,0.0 11.2129974365,0.0 c 0.0,0.0 0.0,-24.4769897461 0.0,-24.4769897461 c 4.35900878906,-2.35301208496 3.83100891113,-7.48899841309 3.83100891113,-7.48899841309 Z M 0.0234985351562,0 c -1.52299499512,0 -2.75700378418,-1.23399353027 -2.75700378418,-2.75700378418 c 0.0,-1.52299499512 1.23400878906,-2.75700378418 2.75700378418,-2.75700378418 c 1.52299499512,0.0 2.75700378418,1.23400878906 2.75700378418,2.75700378418 c 0.0,1.52200317383 -1.23400878906,2.75700378418 -2.75700378418,2.75700378418 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
deleted file mode 100644
index c2215f1..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_signal_flashlight"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="ic_signal_flashlight_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 37.8337860107,-39.2975769043 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,40.9278411865 40.9884796143,40.9278411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-40.9392852783 -41.1884460449,-40.9392852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 8.34049987793,5.6930847168 c 0.0,0.0 29.7749786377,29.7999725342 29.7749786377,29.7999725342 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="1"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="flashlight"
-                android:translateX="25.06235"
-                android:translateY="22.48294" >
-                <path
-                    android:name="light"
-                    android:pathData="M -9.40809631348,-23.6970062256 c 0.0,0.0 18.8699951172,0.0 18.8699951172,0.0 c 0.0,0.0 0.0,3.91700744629 0.0,3.91700744629 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,-3.91700744629 0.0,-3.91700744629 Z M 9.4615020752,-15.6629943848 c 0.0,0.0 0.0,-0.639999389648 0.0,-0.639999389649 c 0.0,0.0 -18.8699951172,0.0 -18.8699951172,0.0 c 0.0,0.0 0.0,0.639999389648 0.0,0.639999389649 c 0.0,0.0 -0.581008911133,5.18899536133 3.82598876953,7.52299499512 c 0.0,0.0 0.0,24.4429931641 0.0,24.4429931641 c 0.0,0.0 11.2129974365,0.0 11.2129974365,0.0 c 0.0,0.0 0.0,-24.4769897461 0.0,-24.4769897461 c 4.35900878906,-2.35301208496 3.83100891113,-7.48899841309 3.83100891113,-7.48899841309 Z M 0.0234985351562,0 c -1.52299499512,0 -2.75700378418,-1.23399353027 -2.75700378418,-2.75700378418 c 0.0,-1.52299499512 1.23400878906,-2.75700378418 2.75700378418,-2.75700378418 c 1.52299499512,0.0 2.75700378418,1.23400878906 2.75700378418,2.75700378418 c 0.0,1.52200317383 -1.23400878906,2.75700378418 -2.75700378418,2.75700378418 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location.xml b/packages/SystemUI/res/drawable/ic_signal_location.xml
new file mode 100644
index 0000000..2f60580
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_signal_location.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <group
+        android:translateX="0.02"
+        android:translateY="0.82">
+        <path
+            android:pathData="M12,2C8.13,2 5,5.13 5,9c0,4.17 4.42,9.92 6.24,12.11 0.4,0.48 1.13,0.48 1.53,0C14.58,18.92 19,13.17 19,9c0,-3.87 -3.13,-7 -7,-7zM12,11.5a2.5,2.5 0,0 1,0 -5,2.5 2.5,0 0,1 0,5z"
+            android:fillColor="#FFFFFFFF"/>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
deleted file mode 100644
index 439851d..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:alpha="1.0"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_signal_location"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="ic_signal_location_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 38.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 7.3759765625,7.55284118652 7.3759765625,7.55284118652 c 0.0,0.0 -2.61698913574,2.0938873291 -2.61698913574,2.0938873291 c 0.0,0.0 -7.57595825195,-7.56428527832 -7.57595825195,-7.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 6.44050598145,1.9430847168 c 0.0,0.0 0.374984741211,0.399978637695 0.374984741211,0.399978637695 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="0"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="location"
-                android:translateX="23.481"
-                android:translateY="18.71151" >
-                <path
-                    android:name="pin"
-                    android:pathData="M 1.76899719238,-20.011505127 c -7.69999694824,0.0 -14.0,6.30000305176 -14.0,14.0 c 0.0,10.5 14.0,26.0 14.0,26.0 c 0.0,0.0 14.0,-15.5 14.0,-26.0 c 0.0,-7.69999694824 -6.30000305176,-14.0 -14.0,-14.0 Z M 1.76899719238,-1.01150512695 c -2.80000305176,0.0 -5.0,-2.19999694824 -5.0,-5.0 c 0.0,-2.80000305176 2.19999694824,-5.0 5.0,-5.0 c 2.80000305176,0.0 5.0,2.19999694824 5.0,5.0 c 0.0,2.80000305176 -2.19999694824,5.0 -5.0,5.0 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
deleted file mode 100644
index d4b8673..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_signal_location"
-        android:translateX="21.9995"
-        android:translateY="25.73401" >
-        <group
-            android:name="ic_signal_location_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 40.9884796143,41.1153411865 40.9884796143,41.1153411865 c 0.0,0.0 -2.61700439453,2.0938873291 -2.61700439453,2.0938873291 c 0.0,0.0 -41.1884460449,-41.1267852783 -41.1884460449,-41.1267852783 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 6.44050598145,1.9430847168 c 0.0,0.0 33.5749816895,33.4499664307 33.5749816895,33.4499664307 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="1"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="location"
-                android:translateX="23.481"
-                android:translateY="18.71151" >
-                <path
-                    android:name="pin"
-                    android:pathData="M 1.76899719238,-20.011505127 c -7.69999694824,0.0 -14.0,6.30000305176 -14.0,14.0 c 0.0,10.5 14.0,26.0 14.0,26.0 c 0.0,0.0 14.0,-15.5 14.0,-26.0 c 0.0,-7.69999694824 -6.30000305176,-14.0 -14.0,-14.0 Z M 1.76899719238,-1.01150512695 c -2.80000305176,0.0 -5.0,-2.19999694824 -5.0,-5.0 c 0.0,-2.80000305176 2.19999694824,-5.0 5.0,-5.0 c 2.80000305176,0.0 5.0,2.19999694824 5.0,5.0 c 0.0,2.80000305176 -2.19999694824,5.0 -5.0,5.0 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="1" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 03bba53..4165830 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
 -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android">
     <shape>
-        <solid android:color="@color/qs_background_dark"/>
+        <solid android:color="?android:attr/colorBackgroundFloating"/>
     </shape>
 </inset>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index e043836..c82eddc 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -14,41 +14,58 @@
      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"
-    android:visibility="gone">
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:fitsSystemWindows="true"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@android:color/black"
+        android:visibility="gone">
 
+    <!-- This progressbar is activated while we're switching users. -->
     <ProgressBar
-        android:id="@+id/countdown_progress"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_user_switcher_progress_bar_height"
-        style="@style/CarUserSwitcher.ProgressBar"
-        android:layout_marginTop="@dimen/car_user_switcher_progress_bar_margin_top"
-        android:layout_alignParentTop="true"/>
-
-    <com.android.systemui.statusbar.car.UserGridView
-        android:id="@+id/user_grid"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="@dimen/car_margin"
-        android:layout_marginRight="@dimen/car_margin"
-        android:layout_centerInParent="true" />
-
-    <com.android.systemui.statusbar.car.PageIndicator
-        android:id="@+id/user_switcher_page_indicator"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/car_page_indicator_dot_diameter"
-        android:layout_marginTop="@dimen/car_page_indicator_margin_top"
-        android:layout_below="@+id/user_grid" />
-
-    <Button
-        android:id="@+id/start_driving"
+        android:id="@+id/switching_users"
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/car_start_driving_height"
-        android:text="@string/start_driving"
-        style="@style/CarUserSwitcher.StartDrivingButton"
-        android:layout_alignParentBottom="true"
-        android:layout_centerHorizontal="true" />
-</RelativeLayout>
+        android:layout_height="wrap_content"
+        android:indeterminate="true"
+        android:visibility="gone"
+        android:layout_gravity="center" />
+
+    <RelativeLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <!-- This progress bar is the countdown timer. -->
+        <ProgressBar
+            android:id="@+id/countdown_progress"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_user_switcher_progress_bar_height"
+            style="@style/CarUserSwitcher.ProgressBar"
+            android:layout_marginTop="@dimen/car_user_switcher_progress_bar_margin_top"
+            android:layout_alignParentTop="true"/>
+
+        <com.android.systemui.statusbar.car.UserGridView
+            android:id="@+id/user_grid"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/car_margin"
+            android:layout_marginRight="@dimen/car_margin"
+            android:layout_centerInParent="true" />
+
+        <com.android.systemui.statusbar.car.PageIndicator
+            android:id="@+id/user_switcher_page_indicator"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/car_page_indicator_dot_diameter"
+            android:layout_marginTop="@dimen/car_page_indicator_margin_top"
+            android:layout_below="@+id/user_grid" />
+
+        <Button
+            android:id="@+id/start_driving"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/car_start_driving_height"
+            android:text="@string/start_driving"
+            style="@style/CarUserSwitcher.StartDrivingButton"
+            android:layout_alignParentBottom="true"
+            android:layout_centerHorizontal="true" />
+    </RelativeLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 143a462..ef9cf4a 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -39,7 +39,7 @@
             android:layout_height="wrap_content"
             android:gravity="center_horizontal"
             android:textStyle="italic"
-            android:textColor="#ffffff"
+            android:textColor="?attr/bgProtectSecondaryTextColor"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:visibility="gone" />
 
@@ -49,7 +49,7 @@
             android:layout_height="wrap_content"
             android:gravity="center_horizontal"
             android:textStyle="italic"
-            android:textColor="#ffffff"
+            android:textColor="?attr/bgProtectSecondaryTextColor"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:accessibilityLiveRegion="polite" />
 
@@ -68,7 +68,8 @@
         android:layout_gravity="bottom|end"
         android:src="@drawable/ic_camera_alt_24dp"
         android:scaleType="center"
-        android:contentDescription="@string/accessibility_camera_button" />
+        android:contentDescription="@string/accessibility_camera_button"
+        android:tint="?attr/bgProtectTextColor" />
 
     <com.android.systemui.statusbar.KeyguardAffordanceView
         android:id="@+id/left_button"
@@ -77,7 +78,8 @@
         android:layout_gravity="bottom|start"
         android:src="@drawable/ic_phone_24dp"
         android:scaleType="center"
-        android:contentDescription="@string/accessibility_phone_button" />
+        android:contentDescription="@string/accessibility_phone_button"
+        android:tint="?attr/bgProtectTextColor" />
 
     <com.android.systemui.statusbar.phone.LockIcon
         android:id="@+id/lock_icon"
@@ -86,7 +88,8 @@
         android:layout_gravity="bottom|center_horizontal"
         android:src="@drawable/ic_lock_24dp"
         android:contentDescription="@string/accessibility_unlock_button"
-        android:scaleType="center" />
+        android:scaleType="center"
+        android:tint="?attr/bgProtectTextColor" />
 
     <include layout="@layout/keyguard_bottom_area_overlay" />
 
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index c5f2f4a..71a681c 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -63,7 +63,7 @@
         android:gravity="center_vertical"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="#ffffff"
+        android:textColor="?attr/bgProtectSecondaryTextColor"
         android:singleLine="true" />
 
 </com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index fb4ac04..62a1756 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -18,7 +18,6 @@
     android:id="@+id/quick_settings_container"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="?android:attr/colorPrimaryDark"
     android:clipToPadding="false"
     android:clipChildren="false">
 
@@ -27,6 +26,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@drawable/qs_background_primary"
+        android:alpha="0.8"
         android:elevation="4dp" />
 
     <com.android.systemui.qs.QSPanel
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 66c5dd5..97376c3 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -35,7 +35,7 @@
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="24dp"
+        android:layout_height="32dp"
         android:layout_alignParentEnd="true"
         android:clipChildren="false"
         android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 2e22943..25c87d3 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -32,6 +32,7 @@
         android:layout_width="wrap_content"
         android:paddingEnd="6dp"
         android:src="@drawable/stat_sys_vpn_ic"
+        android:tint="@color/background_protect_secondary"
         android:contentDescription="@string/accessibility_vpn_on"
         />
     <FrameLayout
diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
index 78b580f..3528f9e 100644
--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
@@ -30,7 +30,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:singleLine="true"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
         android:textSize="@dimen/qs_time_collapsed_size"
         android:gravity="center_vertical"
         systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 07a9a60..bef0830 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -27,7 +27,6 @@
 
     <include
         layout="@layout/keyguard_status_view"
-        android:layout_height="wrap_content"
         android:visibility="gone" />
 
     <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
diff --git a/packages/SystemUI/res/layout/status_bar_no_notifications.xml b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
index 6f87184..ed4bc67 100644
--- a/packages/SystemUI/res/layout/status_bar_no_notifications.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
@@ -27,7 +27,7 @@
             android:layout_height="64dp"
             android:paddingTop="28dp"
             android:gravity="top|center_horizontal"
-            android:textColor="#e6ffffff"
+            android:textColor="?attr/bgProtectTextColor"
             android:textSize="16sp"
             android:text="@string/empty_shade_text"/>
 </com.android.systemui.statusbar.EmptyShadeView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
index efb273f..eefa9bc 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
@@ -30,5 +30,6 @@
             android:focusable="true"
             android:contentDescription="@string/accessibility_clear_all"
             android:text="@string/clear_all_notifications_text"
+            android:textColor="?attr/bgProtectTextColor"
             android:textAllCaps="true"/>
 </com.android.systemui.statusbar.DismissView>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index ce57bf9..81f0138 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -127,5 +127,7 @@
 
     <attr name="lightIconTheme" format="reference" />
     <attr name="darkIconTheme" format="reference" />
+    <attr name="bgProtectTextColor" format="color" />
+    <attr name="bgProtectSecondaryTextColor" format="color" />
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 340cd79..d71bfca 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -815,4 +815,7 @@
 
     <dimen name="qs_gutter_height">6dp</dimen>
 
+    <!-- Intended corner radius when drawing the mobile signal -->
+    <dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f3ce40f..a1bf3a2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1455,6 +1455,9 @@
         Hints that the user's only option is to block all of the app's notifications. -->
     <string name="notification_default_channel_desc">This app doesn\'t have notification categories</string>
 
+    <!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
+    <string name="notification_unblockable_desc">Notifications from this app can\'t be turned off</string>
+
     <!-- Notification: Control panel: Label that shows how many channels this application has
         defined, describing the current notification channel as "1 out of n notification categories from this app". -->
     <plurals name="notification_num_channels_desc">
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b046256..f942be6 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -155,16 +155,16 @@
 
     <style name="TextAppearance.StatusBar.Expanded.Clock">
         <item name="android:textSize">@dimen/qs_time_expanded_size</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textStyle">normal</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.Date">
-        <item name="android:textSize">@dimen/qs_date_collapsed_size</item>
+        <item name="android:textSize">@dimen/qs_time_expanded_size</item>
         <item name="android:textStyle">normal</item>
-        <item name="android:textColor">?android:attr/textColorSecondary</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:fontFamily">sans-serif</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
@@ -293,7 +293,18 @@
     <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="lightIconTheme">@style/DualToneLightTheme</item>
         <item name="darkIconTheme">@style/DualToneDarkTheme</item>
+        <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
+        <item name="pinDividerColor">@color/pin_divider_color</item>
+        <item name="pinDeleteColor">@color/pin_delete_color</item>
+        <item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
     </style>
+
+    <style name="LockPatternStyle">
+        <item name="*android:regularColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="*android:successColor">?android:attr/textColorPrimaryInverse</item>
+    </style>
+
     <style name="qs_theme" parent="systemui_theme">
         <item name="lightIconTheme">@style/QSIconTheme</item>
         <item name="darkIconTheme">@style/QSIconTheme</item>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 616e5b9..165ca2a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -75,8 +75,7 @@
     }
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
-        super(new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault), attrs,
-                defStyle);
+        super(context, attrs, defStyle);
         mSecurityModel = new KeyguardSecurityModel(context);
         mLockPatternUtils = new LockPatternUtils(context);
         mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index db1e8a9..2262869 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -21,7 +21,9 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Color;
 import android.os.UserHandle;
+import android.support.v4.graphics.ColorUtils;
 import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
@@ -37,6 +39,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ChargingView;
+import com.android.systemui.statusbar.policy.DateView;
 
 import java.util.Locale;
 
@@ -48,7 +51,7 @@
     private final AlarmManager mAlarmManager;
 
     private TextView mAlarmStatusView;
-    private TextClock mDateView;
+    private DateView mDateView;
     private TextClock mClockView;
     private TextView mOwnerInfo;
     private ViewGroup mClockContainer;
@@ -56,7 +59,8 @@
 
     private View[] mVisibleInDoze;
     private boolean mPulsing;
-    private boolean mDark;
+    private float mDarkAmount;
+    private int mTextColor;
 
     private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
@@ -118,12 +122,12 @@
         mAlarmStatusView = findViewById(R.id.alarm_status);
         mDateView = findViewById(R.id.date_view);
         mClockView = findViewById(R.id.clock_view);
-        mDateView.setShowCurrentUserTime(true);
         mClockView.setShowCurrentUserTime(true);
         mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
         mOwnerInfo = findViewById(R.id.owner_info);
         mBatteryDoze = findViewById(R.id.battery_doze);
         mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
+        mTextColor = mClockView.getCurrentTextColor();
 
         boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
         setEnableMarquee(shouldMarquee);
@@ -154,8 +158,7 @@
     }
 
     public void refreshTime() {
-        mDateView.setFormat24Hour(Patterns.dateView);
-        mDateView.setFormat12Hour(Patterns.dateView);
+        mDateView.setDatePattern(Patterns.dateViewSkel);
 
         mClockView.setFormat12Hour(Patterns.clockView12);
         mClockView.setFormat24Hour(Patterns.clockView24);
@@ -187,6 +190,10 @@
                 ((MarginLayoutParams) mClockView.getLayoutParams()).bottomMargin;
     }
 
+    public float getClockTextSize() {
+        return mClockView.getTextSize();
+    }
+
     public static String formatNextAlarm(Context context, AlarmManager.AlarmClockInfo info) {
         if (info == null) {
             return "";
@@ -246,7 +253,7 @@
     // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
     // This is an optimization to ensure we only recompute the patterns when the inputs change.
     private static final class Patterns {
-        static String dateView;
+        static String dateViewSkel;
         static String clockView12;
         static String clockView24;
         static String cacheKey;
@@ -254,7 +261,7 @@
         static void update(Context context, boolean hasAlarm) {
             final Locale locale = Locale.getDefault();
             final Resources res = context.getResources();
-            final String dateViewSkel = res.getString(hasAlarm
+            dateViewSkel = res.getString(hasAlarm
                     ? R.string.abbrev_wday_month_day_no_year_alarm
                     : R.string.abbrev_wday_month_day_no_year);
             final String clockView12Skel = res.getString(R.string.clock_12hr_format);
@@ -262,8 +269,6 @@
             final String key = locale.toString() + dateViewSkel + clockView12Skel + clockView24Skel;
             if (key.equals(cacheKey)) return;
 
-            dateView = DateFormat.getBestDateTimePattern(locale, dateViewSkel);
-
             clockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
             // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
             // format.  The following code removes the AM/PM indicator if we didn't want it.
@@ -281,12 +286,13 @@
         }
     }
 
-    public void setDark(boolean dark) {
-        if (mDark == dark) {
+    public void setDark(float darkAmount) {
+        if (mDarkAmount == darkAmount) {
             return;
         }
-        mDark = dark;
+        mDarkAmount = darkAmount;
 
+        boolean dark = darkAmount == 1;
         final int N = mClockContainer.getChildCount();
         for (int i = 0; i < N; i++) {
             View child = mClockContainer.getChildAt(i);
@@ -297,6 +303,7 @@
         }
         updateDozeVisibleViews();
         mBatteryDoze.setDark(dark);
+        mClockView.setTextColor(ColorUtils.blendARGB(mTextColor, Color.WHITE, darkAmount));
     }
 
     public void setPulsing(boolean pulsing) {
@@ -306,7 +313,7 @@
 
     private void updateDozeVisibleViews() {
         for (View child : mVisibleInDoze) {
-            child.setAlpha(mDark && mPulsing ? 0.8f : 1);
+            child.setAlpha(mDarkAmount == 1 && mPulsing ? 0.8f : 1);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index c43820d..7e81173 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.Typeface;
@@ -127,12 +128,13 @@
             mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
                     getContext().getResources().getDimensionPixelSize(
                             R.dimen.password_char_padding));
+            int textColor = a.getColor(R.styleable.PasswordTextView_android_textColor, Color.WHITE);
+            mDrawPaint.setColor(textColor);
         } finally {
             a.recycle();
         }
         mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
         mDrawPaint.setTextAlign(Paint.Align.CENTER);
-        mDrawPaint.setColor(0xffffffff);
         mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0));
         mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
                 Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index cf8747e..6476416 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -71,6 +71,7 @@
 
     private int mLightModeBackgroundColor;
     private int mLightModeFillColor;
+    private float mDarkIntensity;
 
     public BatteryMeterView(Context context) {
         this(context, null, 0);
@@ -238,6 +239,7 @@
 
     @Override
     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
+        mDarkIntensity = darkIntensity;
         float intensity = DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0;
         int foreground = getColorForDarkIntensity(intensity, mLightModeFillColor,
                 mDarkModeFillColor);
@@ -254,6 +256,14 @@
         }
     }
 
+    public void setFillColor(int color) {
+        if (mLightModeFillColor == color) {
+            return;
+        }
+        mLightModeFillColor = color;
+        onDarkChanged(new Rect(), mDarkIntensity, DarkIconDispatcher.DEFAULT_ICON_TINT);
+    }
+
     private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
         return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 3532f41..2d5d198 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -194,6 +194,12 @@
             mKeyguardViewMediator.startKeyguardExitAnimation(startTime, fadeoutDuration);
             Trace.endSection();
         }
+
+        @Override
+        public void onShortPowerPressedGoHome() {
+            checkPermission();
+            mKeyguardViewMediator.onShortPowerPressedGoHome();
+        }
     };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 7ccb431..b8de9f3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2017,6 +2017,10 @@
         Trace.endSection();
     }
 
+    public void onShortPowerPressedGoHome() {
+        // do nothing
+    }
+
     public ViewMediatorCallback getViewMediatorCallback() {
         return mViewMediatorCallback;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
index ec5f9e7..493d244 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
@@ -30,13 +30,13 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.widget.Toast;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -166,7 +166,9 @@
         }
         if (!mPluginMap.containsKey(listener)) return;
         mPluginMap.remove(listener).destroy();
-        stopListening();
+        if (mPluginMap.size() == 0) {
+            stopListening();
+        }
     }
 
     private void startListening() {
@@ -237,7 +239,9 @@
                 mContext.getSystemService(NotificationManager.class).notifyAsUser(pkg,
                         SystemMessage.NOTE_PLUGIN, nb.build(), UserHandle.ALL);
             }
-            clearClassLoader(pkg);
+            if (clearClassLoader(pkg)) {
+                Toast.makeText(mContext, "Reloading " + pkg, Toast.LENGTH_LONG).show();
+            }
             if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                 for (PluginInstanceManager manager : mPluginMap.values()) {
                     manager.onPackageChange(pkg);
@@ -259,8 +263,8 @@
         return classLoader;
     }
 
-    private void clearClassLoader(String pkg) {
-        mClassLoaders.remove(pkg);
+    private boolean clearClassLoader(String pkg) {
+        return mClassLoaders.remove(pkg) != null;
     }
 
     ClassLoader getParentClassLoader() {
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 c0509c1..2e7012e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -37,7 +37,7 @@
 /** Quick settings tile: Airplane mode **/
 public class AirplaneModeTile extends QSTileImpl<BooleanState> {
     private final Icon mIcon =
-            ResourceIcon.get(R.drawable.ic_signal_airplane_disable);
+            ResourceIcon.get(R.drawable.ic_signal_airplane);
     private final GlobalSetting mSetting;
 
     private boolean mListening;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 74cc0ec..336c581 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -20,9 +20,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.service.quicksettings.Tile;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.style.RelativeSizeSpan;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -35,9 +32,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.BatteryInfo;
 import com.android.settingslib.graph.BatteryMeterDrawableBase;
-import com.android.settingslib.graph.UsageView;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.DetailAdapter;
@@ -187,14 +182,6 @@
             ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
             Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
             checkbox.setChecked(mPowerSave);
-            BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
-                @Override
-                public void onBatteryInfoLoaded(BatteryInfo info) {
-                    if (mCurrentView != null) {
-                        bindBatteryInfo(info);
-                    }
-                }
-            });
             final TextView batterySaverTitle =
                     (TextView) mCurrentView.findViewById(android.R.id.title);
             final TextView batterySaverSummary =
@@ -216,23 +203,6 @@
             }
         }
 
-        private void bindBatteryInfo(BatteryInfo info) {
-            SpannableStringBuilder builder = new SpannableStringBuilder();
-            builder.append(info.batteryPercentString, new RelativeSizeSpan(2.6f),
-                    Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-            if (info.remainingLabel != null) {
-                if (mContext.getResources().getBoolean(R.bool.quick_settings_wide)) {
-                    builder.append(' ');
-                } else {
-                    builder.append('\n');
-                }
-                builder.append(info.remainingLabel);
-            }
-            ((TextView) mCurrentView.findViewById(R.id.charge_and_estimation)).setText(builder);
-
-            info.bindHistory((UsageView) mCurrentView.findViewById(R.id.battery_usage));
-        }
-
         @Override
         public void onClick(View v) {
             mBatteryController.setPowerSaveMode(!mPowerSave);
@@ -278,4 +248,4 @@
             }
         };
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 97a12c2..40fe484 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -34,7 +34,7 @@
 /** Quick settings tile: Invert colors **/
 public class ColorInversionTile extends QSTileImpl<BooleanState> {
 
-    private final Icon mIcon = ResourceIcon.get(drawable.ic_invert_colors_disable);
+    private final Icon mIcon = ResourceIcon.get(drawable.ic_invert_colors);
     private final SecureSetting mSetting;
 
     private boolean mListening;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 8c6363a..71f253c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -71,8 +71,6 @@
     private static final QSTile.Icon TOTAL_SILENCE =
             ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
 
-    private final Icon mDisable = ResourceIcon.get(R.drawable.ic_qs_dnd_off);
-
     private final ZenModeController mController;
     private final DndDetailAdapter mDetailAdapter;
 
@@ -187,7 +185,7 @@
                         R.string.accessibility_quick_settings_dnd_alarms_on);
                 break;
             default:
-                state.icon = mDisable;
+                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
                 state.label = mContext.getString(R.string.quick_settings_dnd_label);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_dnd);
@@ -317,7 +315,7 @@
                 mZenPanel.init(mController);
                 mZenPanel.addOnAttachStateChangeListener(this);
                 mZenPanel.setCallback(mZenModePanelCallback);
-                mZenPanel.setEmptyState(R.drawable.ic_qs_dnd_off, R.string.dnd_is_off);
+                mZenPanel.setEmptyState(R.drawable.ic_qs_dnd_detail_empty, R.string.dnd_is_off);
             }
             updatePanel();
             return mZenPanel;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index b436e17..e6ac908 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -35,7 +35,7 @@
 public class FlashlightTile extends QSTileImpl<BooleanState> implements
         FlashlightController.FlashlightListener {
 
-    private final Icon mIcon = ResourceIcon.get(R.drawable.ic_signal_flashlight_disable);
+    private final Icon mIcon = ResourceIcon.get(R.drawable.ic_signal_flashlight);
     private final FlashlightController mFlashlightController;
 
     public FlashlightTile(QSHost host) {
@@ -103,9 +103,8 @@
         }
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         if (!mFlashlightController.isAvailable()) {
-            Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_enable)
-                    .mutate();
-            state.icon = new DrawableIcon(icon);
+            state.icon = mIcon;
+            state.slash.isSlashed = true;
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_flashlight_unavailable);
             state.state = Tile.STATE_UNAVAILABLE;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 1c7c578..c17573d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -39,7 +39,7 @@
     static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
              "com.android.settings", "com.android.settings.TetherSettings"));
 
-    private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot_disable);
+    private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot);
     private final Icon mUnavailable = ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
 
     private final HotspotController mController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 96f2f68..5e66334 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -37,7 +37,7 @@
 /** Quick settings tile: Location **/
 public class LocationTile extends QSTileImpl<BooleanState> {
 
-    private final Icon mIcon = ResourceIcon.get(drawable.ic_signal_location_disable);
+    private final Icon mIcon = ResourceIcon.get(drawable.ic_signal_location);
 
     private final LocationController mController;
     private final KeyguardMonitor mKeyguard;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 8aa1e43..2a12769 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -79,8 +79,7 @@
         state.value = isActivated;
         state.label = state.contentDescription =
                 mContext.getString(R.string.quick_settings_night_display_label);
-        state.icon = ResourceIcon.get(isActivated ? R.drawable.ic_qs_night_display_on
-                : R.drawable.ic_qs_night_display_off);
+        state.icon = ResourceIcon.get(R.drawable.ic_qs_night_display_on);
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 2d47c7b..a7b845e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -578,7 +578,8 @@
         if (requiresRotation) {
             // Rotate the screenshot to the current orientation
             Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
-                    mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
+                    mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888,
+                    mScreenBitmap.hasAlpha(), mScreenBitmap.getColorSpace());
             Canvas c = new Canvas(ss);
             c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
             c.rotate(degrees);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 0b09acc..f750815 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -79,6 +79,7 @@
     private void addDivider(Configuration configuration) {
         mView = (DividerView)
                 LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
+        mView.injectDependencies(mWindowManager, mDividerState);
         mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
         mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
         final int size = mContext.getResources().getDimensionPixelSize(
@@ -87,7 +88,6 @@
         final int width = landscape ? size : MATCH_PARENT;
         final int height = landscape ? MATCH_PARENT : size;
         mWindowManager.add(mView, width, height);
-        mView.injectDependencies(mWindowManager, mDividerState);
     }
 
     private void removeDivider() {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
index 353a974..3a5c61e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
@@ -22,4 +22,5 @@
 public class DividerState {
     public boolean animateAfterRecentsDrawn;
     public boolean growAfterRecentsDrawn;
+    public float mRatioPositionBeforeMinimized;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 9e2ec571fa..2bda1df 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -364,6 +364,17 @@
     public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState) {
         mWindowManager = windowManager;
         mState = dividerState;
+
+        // Set the previous position ratio before minimized state after attaching this divider
+        if (mStableInsets.isEmpty()) {
+            SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+        }
+        int position = (int) (mState.mRatioPositionBeforeMinimized *
+                (isHorizontalDivision() ? mDisplayHeight : mDisplayWidth));
+        mSnapAlgorithm = null;
+        initializeSnapAlgorithm();
+        mDividerPositionBeforeMinimized = mSnapAlgorithm.calculateNonDismissingSnapTarget(position)
+                .position;
     }
 
     public WindowManagerProxy getWindowManagerProxy() {
@@ -719,19 +730,12 @@
             mHandle.setAlpha(minimized ? 0f : 1f);
             mDockedStackMinimized = minimized;
         } else if (mDockedStackMinimized != minimized) {
-            if (mStableInsets.isEmpty()) {
-                SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
-            }
             mMinimizedSnapAlgorithm = null;
             mDockedStackMinimized = minimized;
             initializeSnapAlgorithm();
             if (mIsInMinimizeInteraction != minimized) {
                 if (minimized) {
                     mIsInMinimizeInteraction = true;
-                    mDividerPositionBeforeMinimized = DockedDividerUtils.calculateMiddlePosition(
-                            isHorizontalDivision(), mStableInsets, mDisplayWidth, mDisplayHeight,
-                            mDividerSize);
-
                     int position = mMinimizedSnapAlgorithm.getMiddleTarget().position;
                     resizeStack(position, position, mMinimizedSnapAlgorithm.getMiddleTarget());
                 } else {
@@ -776,7 +780,7 @@
             mIsInMinimizeInteraction = true;
             if (minimized && (mCurrentAnimator == null || !mCurrentAnimator.isRunning())
                     && (mDividerPositionBeforeMinimized <= 0 || !mAdjustedForIme)) {
-                mDividerPositionBeforeMinimized = getCurrentPosition();
+                savePositionBeforeMinimized();
             }
             mMinimizedSnapAlgorithm = null;
             mDockedStackMinimized = minimized;
@@ -836,10 +840,16 @@
         // Only get new position if home stack is resizable, ime is open and not minimized
         // (including the animation)
         if (mHomeStackResizable && adjustedForIme && !mIsInMinimizeInteraction) {
-            mDividerPositionBeforeMinimized = getCurrentPosition();
+            savePositionBeforeMinimized();
         }
     }
 
+    private void savePositionBeforeMinimized() {
+        mDividerPositionBeforeMinimized = getCurrentPosition();
+        mState.mRatioPositionBeforeMinimized = (float) mDividerPositionBeforeMinimized /
+                (isHorizontalDivision() ? mDisplayHeight : mDisplayWidth);
+    }
+
     private void resetBackground() {
         mBackground.setPivotX(mBackground.getWidth() / 2);
         mBackground.setPivotY(mBackground.getHeight() / 2);
@@ -1198,14 +1208,6 @@
                 mDockSide, mDividerSize);
         mEntranceAnimationRunning = true;
 
-        // Insets might not have been fetched yet, so fetch manually if needed.
-        if (mStableInsets.isEmpty()) {
-            SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
-            mSnapAlgorithm = null;
-            mMinimizedSnapAlgorithm = null;
-            initializeSnapAlgorithm();
-        }
-
         resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
                 mSnapAlgorithm.getMiddleTarget());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index a2c782e..578a18a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -142,7 +142,9 @@
             Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
             ActivityOptions options = ActivityOptions.makeBasic();
             options.setLaunchTaskId(pendingRecord.taskId);
-            options.setTaskOverlay(true, false /* canResume */);
+            // Set as task overlay and allow to resume, so that when an app enters split-screen and
+            // becomes paused, the overlay will still be shown.
+            options.setTaskOverlay(true, true /* canResume */);
             intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.reason);
             mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index b15f090..e12b574 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -23,6 +23,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
 import android.graphics.Color;
@@ -55,7 +56,7 @@
 
     private final int mMinBackgroundRadius;
     private final Paint mCirclePaint;
-    private final int mInverseColor;
+    private final int mDarkIconColor;
     private final int mNormalColor;
     private final ArgbEvaluator mColorInterpolator;
     private final FlingAnimationUtils mFlingAnimationUtils;
@@ -126,17 +127,21 @@
     public KeyguardAffordanceView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ImageView);
+
         mCirclePaint = new Paint();
         mCirclePaint.setAntiAlias(true);
         mCircleColor = 0xffffffff;
         mCirclePaint.setColor(mCircleColor);
 
-        mNormalColor = 0xffffffff;
-        mInverseColor = 0xff000000;
+        mNormalColor = a.getColor(android.R.styleable.ImageView_tint, 0xffffffff);
+        mDarkIconColor = 0xff000000;
         mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize(
                 R.dimen.keyguard_affordance_min_background_radius);
         mColorInterpolator = new ArgbEvaluator();
         mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.3f);
+
+        a.recycle();
     }
 
     public void setImageDrawable(@Nullable Drawable drawable, boolean tint) {
@@ -177,7 +182,7 @@
         Drawable drawable = getDrawable().mutate();
         float alpha = mCircleRadius / mMinBackgroundRadius;
         alpha = Math.min(1.0f, alpha);
-        int color = (int) mColorInterpolator.evaluate(alpha, mNormalColor, mInverseColor);
+        int color = (int) mColorInterpolator.evaluate(alpha, mNormalColor, mDarkIconColor);
         drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 49c3f7e..25ef478 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -65,21 +65,22 @@
     private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
 
     private final Context mContext;
-    private final ViewGroup mIndicationArea;
-    private final KeyguardIndicationTextView mTextView;
-    private final KeyguardIndicationTextView mDisclosure;
+    private ViewGroup mIndicationArea;
+    private KeyguardIndicationTextView mTextView;
+    private KeyguardIndicationTextView mDisclosure;
     private final UserManager mUserManager;
     private final IBatteryStats mBatteryInfo;
     private final SettableWakeLock mWakeLock;
 
     private final int mSlowThreshold;
     private final int mFastThreshold;
-    private final LockIcon mLockIcon;
+    private LockIcon mLockIcon;
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     private String mRestingIndication;
     private String mTransientIndication;
     private int mTransientTextColor;
+    private int mInitialTextColor;
     private boolean mVisible;
 
     private boolean mPowerPluggedIn;
@@ -114,6 +115,7 @@
         mIndicationArea = indicationArea;
         mTextView = (KeyguardIndicationTextView) indicationArea.findViewById(
                 R.id.keyguard_indication_text);
+        mInitialTextColor = mTextView != null ? mTextView.getCurrentTextColor() : Color.WHITE;
         mDisclosure = (KeyguardIndicationTextView) indicationArea.findViewById(
                 R.id.keyguard_indication_enterprise_disclosure);
         mLockIcon = lockIcon;
@@ -238,7 +240,7 @@
      * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
      */
     public void showTransientIndication(String transientIndication) {
-        showTransientIndication(transientIndication, Color.WHITE);
+        showTransientIndication(transientIndication, mInitialTextColor);
     }
 
     /**
@@ -273,13 +275,17 @@
         }
 
         if (mVisible) {
-            // Walk down a precedence-ordered list of what should indication
+            // Walk down a precedence-ordered list of what indication
             // should be shown based on user or device state
             if (mDozing) {
                 // If we're dozing, never show a persistent indication.
                 if (!TextUtils.isEmpty(mTransientIndication)) {
+                    // When dozing we ignore the initial text color and use white instead.
+                    // We don't wait to draw black text on a black background.
+                    int color = mTransientTextColor == mInitialTextColor ?
+                            Color.WHITE : mTransientTextColor;
                     mTextView.switchIndication(mTransientIndication);
-                    mTextView.setTextColor(mTransientTextColor);
+                    mTextView.setTextColor(color);
 
                 } else {
                     mTextView.switchIndication(null);
@@ -293,29 +299,29 @@
             String trustManagedIndication = getTrustManagedIndication();
             if (!mUserManager.isUserUnlocked(userId)) {
                 mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
-                mTextView.setTextColor(Color.WHITE);
+                mTextView.setTextColor(mInitialTextColor);
             } else if (!TextUtils.isEmpty(mTransientIndication)) {
                 mTextView.switchIndication(mTransientIndication);
                 mTextView.setTextColor(mTransientTextColor);
             } else if (!TextUtils.isEmpty(trustGrantedIndication)
                     && updateMonitor.getUserHasTrust(userId)) {
                 mTextView.switchIndication(trustGrantedIndication);
-                mTextView.setTextColor(Color.WHITE);
+                mTextView.setTextColor(mInitialTextColor);
             } else if (mPowerPluggedIn) {
                 String indication = computePowerIndication();
                 if (DEBUG_CHARGING_SPEED) {
                     indication += ",  " + (mChargingWattage / 1000) + " mW";
                 }
                 mTextView.switchIndication(indication);
-                mTextView.setTextColor(Color.WHITE);
+                mTextView.setTextColor(mInitialTextColor);
             } else if (!TextUtils.isEmpty(trustManagedIndication)
                     && updateMonitor.getUserTrustIsManaged(userId)
                     && !updateMonitor.getUserHasTrust(userId)) {
                 mTextView.switchIndication(trustManagedIndication);
-                mTextView.setTextColor(Color.WHITE);
+                mTextView.setTextColor(mInitialTextColor);
             } else {
                 mTextView.switchIndication(mRestingIndication);
-                mTextView.setTextColor(Color.WHITE);
+                mTextView.setTextColor(mInitialTextColor);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 427708b..1ffb3b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -154,9 +154,32 @@
             }
         }
 
+        boolean nonBlockable = false;
+        try {
+            final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+            if (Utils.isSystemPackage(getResources(), pm, pkgInfo)) {
+                final int numChannels = mNotificationChannels.size();
+                for (int i = 0; i < numChannels; i++) {
+                    final NotificationChannel notificationChannel = mNotificationChannels.get(i);
+                    // If any of the system channels is not blockable, the bundle is nonblockable
+                    if (!notificationChannel.isBlockableSystem()) {
+                        nonBlockable = true;
+                        break;
+                    }
+                }
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // unlikely.
+        }
+        if (nonBlockablePkgs != null) {
+            nonBlockable |= nonBlockablePkgs.contains(pkg);
+        }
+
         String channelsDescText;
         mNumChannelsView = findViewById(R.id.num_channels_desc);
-        if (mIsSingleDefaultChannel) {
+        if (nonBlockable) {
+            channelsDescText = mContext.getString(R.string.notification_unblockable_desc);
+        } else if (mIsSingleDefaultChannel) {
             channelsDescText = mContext.getString(R.string.notification_default_channel_desc);
         } else {
             switch (mNotificationChannels.size()) {
@@ -188,8 +211,9 @@
             // Multiple channels don't use a channel name for the title.
             channelNameText = mContext.getString(R.string.notification_num_channels,
                     mNotificationChannels.size());
-        } else if (mIsSingleDefaultChannel) {
-            // If this is the default channel, don't use our channel-specific text.
+        } else if (mIsSingleDefaultChannel || nonBlockable) {
+            // If this is the default channel or the app is unblockable,
+            // don't use our channel-specific text.
             channelNameText = mContext.getString(R.string.notification_header_default_channel);
         } else {
             channelNameText = mSingleNotificationChannel.getName();
@@ -218,19 +242,6 @@
             groupDividerView.setVisibility(View.GONE);
         }
 
-        boolean nonBlockable = false;
-        try {
-            final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
-            nonBlockable = Utils.isSystemPackage(getResources(), pm, pkgInfo)
-                    && (mSingleNotificationChannel == null
-                    || !mSingleNotificationChannel.isBlockableSystem());
-        } catch (PackageManager.NameNotFoundException e) {
-            // unlikely.
-        }
-        if (nonBlockablePkgs != null) {
-            nonBlockable |= nonBlockablePkgs.contains(pkg);
-        }
-
         bindButtons(nonBlockable);
 
         // Top-level importance group
@@ -246,12 +257,11 @@
                     (View view) -> {
                         onSettingsClick.onClick(view, mSingleNotificationChannel, appUidF);
                     });
-            if (numTotalChannels > 1) {
-                settingsButton.setText(R.string.notification_all_categories);
-            } else {
+            if (numTotalChannels <= 1 || nonBlockable) {
                 settingsButton.setText(R.string.notification_more_settings);
+            } else {
+                settingsButton.setText(R.string.notification_all_categories);
             }
-
         } else {
             settingsButton.setVisibility(View.GONE);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 7a741ef..14374b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -170,7 +170,7 @@
             openedAmount = Math.min(1.0f, openedAmount);
             mShelfState.openedAmount = openedAmount;
             mShelfState.clipTopAmount = 0;
-            mShelfState.alpha = mAmbientState.isPulsing() ? 0 : 1;
+            mShelfState.alpha = mAmbientState.hasPulsingNotifications() ? 0 : 1;
             mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
             mShelfState.shadowAlpha = 1.0f;
             mShelfState.hideSensitive = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index ab41485..18cc8721 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -308,7 +308,7 @@
         if (state == null) {
             return;
         }
-        if (mQsSignal) {
+        if (mQsSignal && qsIcon != null) {
             icon = qsIcon;
             type = qsType;
         }
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 d84a731..9338887 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.car;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.res.Resources;
 import android.os.CountDownTimer;
 import android.view.View;
@@ -31,11 +33,16 @@
  */
 public class FullscreenUserSwitcher {
     private final View mContainer;
+    private final View mParent;
     private final UserGridView mUserGridView;
     private final UserSwitcherController mUserSwitcherController;
     private final ProgressBar mProgressBar;
+    private final ProgressBar mSwitchingUsers;
     private final int mLoginTimeoutMs;
     private final int mAnimUpdateIntervalMs;
+    private final int mShortAnimDuration;
+
+    private boolean mShowing;
 
     private CountDownTimer mTimer;
 
@@ -43,9 +50,15 @@
             UserSwitcherController userSwitcherController,
             ViewStub containerStub) {
         mUserSwitcherController = userSwitcherController;
-        mContainer = containerStub.inflate();
+        mParent = containerStub.inflate();
+        mContainer = mParent.findViewById(R.id.container);
         mUserGridView = mContainer.findViewById(R.id.user_grid);
         mUserGridView.init(statusBar, mUserSwitcherController);
+        mUserGridView.setUserSelectionListener(record -> {
+            if (!record.isCurrent) {
+                toggleSwitchInProgress(true);
+            }
+        });
 
         PageIndicator pageIndicator = mContainer.findViewById(R.id.user_switcher_page_indicator);
         pageIndicator.setupWithViewPager(mUserGridView);
@@ -54,20 +67,64 @@
         Resources res = mContainer.getResources();
         mLoginTimeoutMs = res.getInteger(R.integer.car_user_switcher_timeout_ms);
         mAnimUpdateIntervalMs = res.getInteger(R.integer.car_user_switcher_anim_update_ms);
+        mShortAnimDuration = res.getInteger(android.R.integer.config_shortAnimTime);
 
         mContainer.findViewById(R.id.start_driving).setOnClickListener(v -> {
             cancelTimer();
             automaticallySelectUser();
         });
+
+        mSwitchingUsers = mParent.findViewById(R.id.switching_users);
     }
 
     public void onUserSwitched(int newUserId) {
         mUserGridView.onUserSwitched(newUserId);
     }
 
+    private void toggleSwitchInProgress(boolean inProgress) {
+        if (inProgress) {
+            crossFade(mSwitchingUsers, mContainer);
+        } else {
+            crossFade(mContainer, mSwitchingUsers);
+        }
+    }
+
+    private void crossFade(View incoming, View outgoing) {
+        incoming.animate()
+            .alpha(1.0f)
+            .setDuration(mShortAnimDuration)
+            .setListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animator) {
+                    incoming.setAlpha(0.0f);
+                    incoming.setVisibility(View.VISIBLE);
+                }
+            });
+
+        outgoing.animate()
+            .alpha(0.0f)
+            .setDuration(mShortAnimDuration)
+            .setListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    outgoing.setVisibility(View.GONE);
+                }
+            });
+    }
+
     public void show() {
-        mContainer.setVisibility(View.VISIBLE);
+        if (mShowing) {
+            return;
+        }
+        mShowing = true;
+        mParent.setVisibility(View.VISIBLE);
         cancelTimer();
+
+        // This would be the case if we were in the middle of a switch.
+        if (mProgressBar.getVisibility() != View.VISIBLE) {
+            return;
+        }
+
         mTimer = new CountDownTimer(mLoginTimeoutMs, mAnimUpdateIntervalMs) {
             @Override
             public void onTick(long msUntilFinished) {
@@ -85,8 +142,10 @@
     }
 
     public void hide() {
+        mShowing = false;
         cancelTimer();
-        mContainer.setVisibility(View.GONE);
+        toggleSwitchInProgress(false);
+        mParent.setVisibility(View.GONE);
     }
 
     private void cancelTimer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index 46f55eea..cfa9864 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -17,11 +17,12 @@
 package com.android.systemui.statusbar.car;
 
 import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -30,6 +31,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.util.UserIcons;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.UserUtil;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -43,7 +45,7 @@
     private StatusBar mStatusBar;
     private UserSwitcherController mUserSwitcherController;
     private Adapter mAdapter;
-    private int mPendingUserId = UserHandle.USER_NULL;
+    private UserSelectionListener mUserSelectionListener;
 
     public UserGridView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -58,16 +60,12 @@
     }
 
     public void onUserSwitched(int newUserId) {
-        if (mPendingUserId == newUserId) {
-            // Bring up security view after user switch is completed.
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    showOfflineAuthUi();
-                }
-            });
-        }
-        mPendingUserId = UserHandle.USER_NULL;
+        // Bring up security view after user switch is completed.
+        post(this::showOfflineAuthUi);
+    }
+
+    public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
+        mUserSelectionListener = userSelectionListener;
     }
 
     void showOfflineAuthUi() {
@@ -136,15 +134,19 @@
             for (int i = position * iconsPerPage; i < limit; i++) {
                 pods.addView(makeUserPod(inflater, context, i, pods));
             }
-
-            // Dynamic parameters since we specify the weightsum dynamically.
-            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
-                    LinearLayout.LayoutParams.MATCH_PARENT,
-                    LinearLayout.LayoutParams.WRAP_CONTENT, limit);
-            container.addView(pods, params);
+            container.addView(pods);
             return pods;
         }
 
+        private Drawable getUserIcon(Context context, UserSwitcherController.UserRecord record) {
+            if (record.isAddUser) {
+                Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs);
+                icon.setTint(Color.WHITE);
+                return icon;
+            }
+            return UserIcons.getDefaultUserIcon(record.resolveId(), /* light= */ true);
+        }
+
         private View makeUserPod(LayoutInflater inflater, Context context,
                 int position, ViewGroup parent) {
             final UserSwitcherController.UserRecord record = mUserAdapter.getItem(position);
@@ -160,45 +162,27 @@
 
             ImageView iconView = (ImageView) view.findViewById(R.id.user_avatar);
             if (record == null || record.picture == null) {
-                iconView.setImageDrawable(mUserAdapter.getDrawable(context, record));
+                iconView.setImageDrawable(getUserIcon(context, record));
             } else {
                 iconView.setImageBitmap(record.picture);
             }
 
             iconView.setOnClickListener(v -> {
-                mPendingUserId = UserHandle.USER_NULL;
                 if (record == null) {
                     return;
                 }
 
-                if (record.isGuest || record.isAddUser) {
-                    mUserSwitcherController.switchTo(record);
-                    return;
+                if (mUserSelectionListener != null) {
+                    mUserSelectionListener.onUserSelected(record);
                 }
 
                 if (record.isCurrent) {
                     showOfflineAuthUi();
                 } else {
-                    mPendingUserId = record.info.id;
                     mUserSwitcherController.switchTo(record);
                 }
             });
 
-            iconView.setOnLongClickListener(v -> {
-                if (record == null || record.isAddUser) {
-                    return false;
-                }
-                if (record.isGuest) {
-                    if (record.isCurrent) {
-                        mUserSwitcherController.switchTo(record);
-                    }
-                    return true;
-                }
-                UserUtil.deleteUserWithPrompt(getContext(), record.info.id,
-                        mUserSwitcherController);
-                return true;
-            });
-
             return view;
         }
 
@@ -247,4 +231,8 @@
             mContainer.notifyDataSetChanged();
         }
     }
+
+    interface UserSelectionListener {
+        void onUserSelected(UserSwitcherController.UserRecord record);
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
index 020dc25..e0f577d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
@@ -15,36 +15,76 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.content.om.IOverlayManager;
 import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
 
 import com.android.systemui.ConfigurationChangedReceiver;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 public class ConfigurationControllerImpl implements ConfigurationController,
         ConfigurationChangedReceiver {
 
     private final ArrayList<ConfigurationListener> mListeners = new ArrayList<>();
+    private final IOverlayManager mOverlayManager;
     private int mDensity;
     private float mFontScale;
+    private Map mActiveOverlays;
 
     public ConfigurationControllerImpl(Context context) {
         Configuration currentConfig = context.getResources().getConfiguration();
+        mOverlayManager = IOverlayManager.Stub.asInterface(
+                ServiceManager.getService(Context.OVERLAY_SERVICE));
         mFontScale = currentConfig.fontScale;
         mDensity = currentConfig.densityDpi;
+        try {
+            mActiveOverlays = mOverlayManager.getAllOverlays(UserHandle.getCallingUserId());
+        } catch (RemoteException e) {
+            mActiveOverlays = new HashMap();
+        }
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        mListeners.forEach(l -> l.onConfigChanged(newConfig));
+        // Avoid concurrent modification exception
+        ArrayList<ConfigurationListener> listeners = new ArrayList<>(mListeners);
+
+        listeners.forEach(l -> {
+            if (mListeners.contains(l)) {
+                l.onConfigChanged(newConfig);
+            }
+        });
         final float fontScale = newConfig.fontScale;
         final int density = newConfig.densityDpi;
         if (density != mDensity || mFontScale != fontScale) {
-            mListeners.forEach(l -> l.onDensityOrFontScaleChanged());
+            listeners.forEach(l -> {
+                if (mListeners.contains(l)) {
+                    l.onDensityOrFontScaleChanged();
+                }
+            });
             mDensity = density;
             mFontScale = fontScale;
         }
+
+        try {
+            Map activeOverlays = mOverlayManager.getAllOverlays(UserHandle.getCallingUserId());
+            if (!mActiveOverlays.equals(activeOverlays)) {
+                mActiveOverlays = activeOverlays;
+                listeners.forEach(l -> {
+                    if (mListeners.contains(l)) {
+                        l.onOverlayChanged();
+                    }
+                });
+            }
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
     }
 
     @Override
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 42b09df..6d6250e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -16,9 +16,12 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.TypedValue;
@@ -28,6 +31,7 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
@@ -312,4 +316,10 @@
     public boolean hasOverlappingRendering() {
         return false;
     }
+
+    public void onOverlayChanged() {
+        @ColorInt int textColor = Utils.getColorAttr(mContext, R.attr.bgProtectTextColor);
+        mCarrierLabel.setTextColor(textColor);
+        mBatteryView.setFillColor(textColor);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 52838b0..b888e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -235,4 +235,9 @@
             v.setDecorColor(mIconTint);
         }
     }
+
+    public void setDark(boolean dark) {
+        mNotificationIcons.setDark(dark, false, 0);
+        mShelfIcons.setDark(dark, false, 0);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 3dc6827..e2b9da0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -34,6 +34,7 @@
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.MathUtils;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -47,8 +48,10 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
@@ -58,6 +61,7 @@
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarState;
@@ -65,6 +69,7 @@
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
@@ -112,7 +117,6 @@
     private QS mQs;
     private FrameLayout mQsFrame;
     private KeyguardStatusView mKeyguardStatusView;
-    private TextView mClockView;
     private View mReserveNotificationSpace;
     private View mQsNavbarScrim;
     protected NotificationsQuickSettingsContainer mNotificationContainerParent;
@@ -232,6 +236,8 @@
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private boolean mNoVisibleNotifications = true;
     private ValueAnimator mDarkAnimator;
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private boolean mUserSetupComplete;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -243,6 +249,7 @@
 
     public void setStatusBar(StatusBar bar) {
         mStatusBar = bar;
+        mKeyguardBottomArea.setStatusBar(mStatusBar);
     }
 
     @Override
@@ -250,7 +257,6 @@
         super.onFinishInflate();
         mKeyguardStatusBar = findViewById(R.id.keyguard_header);
         mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
-        mClockView = findViewById(R.id.clock_view);
 
         mNotificationContainerParent = (NotificationsQuickSettingsContainer)
                 findViewById(R.id.notification_container_parent);
@@ -261,10 +267,10 @@
         mNotificationStackScroller.setOnEmptySpaceClickListener(this);
         mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
         mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
-        mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
-        mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
         mLastOrientation = getResources().getConfiguration().orientation;
 
+        initBottomArea();
+
         mQsFrame = findViewById(R.id.qs_frame);
     }
 
@@ -324,6 +330,38 @@
         }
     }
 
+    public void onOverlayChanged() {
+        // Re-inflate the status view group.
+        int index = indexOfChild(mKeyguardStatusView);
+        removeView(mKeyguardStatusView);
+        mKeyguardStatusView = (KeyguardStatusView) LayoutInflater.from(mContext).inflate(
+                R.layout.keyguard_status_view,
+                this,
+                false);
+        addView(mKeyguardStatusView, index);
+
+        // Update keyguard bottom area
+        index = indexOfChild(mKeyguardBottomArea);
+        removeView(mKeyguardBottomArea);
+        mKeyguardBottomArea = (KeyguardBottomAreaView) LayoutInflater.from(mContext).inflate(
+                R.layout.keyguard_bottom_area,
+                this,
+                false);
+        addView(mKeyguardBottomArea, index);
+        initBottomArea();
+    }
+
+    private void initBottomArea() {
+        mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
+        mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
+        mKeyguardBottomArea.setStatusBar(mStatusBar);
+        mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
+    }
+
+    public void setKeyguardIndicationController(KeyguardIndicationController indicationController) {
+        mKeyguardBottomArea.setKeyguardIndicationController(indicationController);
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
@@ -331,7 +369,8 @@
 
         // Update Clock Pivot
         mKeyguardStatusView.setPivotX(getWidth() / 2);
-        mKeyguardStatusView.setPivotY((FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize());
+        mKeyguardStatusView.setPivotY((FONT_HEIGHT - CAP_HEIGHT) / 2048f *
+                mKeyguardStatusView.getClockTextSize());
 
         // Calculate quick setting heights.
         int oldMaxHeight = mQsMaxExpansionHeight;
@@ -2550,7 +2589,7 @@
 
     private void setDarkAmount(float amount) {
         mDarkAmount = amount;
-        mKeyguardStatusView.setDark(amount == 1);
+        mKeyguardStatusView.setDark(mDarkAmount);
         positionClockAndNotifications();
     }
 
@@ -2571,4 +2610,31 @@
             mStatusBar.updateKeyguardMaxNotifications();
         }
     }
+
+    public void refreshTime() {
+        mKeyguardStatusView.refreshTime();
+    }
+
+    public void setStatusAccessibilityImportance(int mode) {
+         mKeyguardStatusView.setImportantForAccessibility(mode);
+    }
+
+    /**
+     * TODO: this should be removed.
+     * It's not correct to pass this view forward because other classes will end up adding
+     * children to it. Theme will be out of sync.
+     * @return bottom area view
+     */
+    public KeyguardBottomAreaView getKeyguardBottomAreaView() {
+        return mKeyguardBottomArea;
+    }
+
+    public void setUserSetupComplete(boolean userSetupComplete) {
+        mUserSetupComplete = userSetupComplete;
+        mKeyguardBottomArea.setUserSetupComplete(userSetupComplete);
+    }
+
+    public LockIcon getLockIcon() {
+        return mKeyguardBottomArea.getLockIcon();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 9cb4488..b970b1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -56,6 +56,7 @@
     private long mDownTime;
     private float mMinExpandHeight;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+    private boolean mPanelUpdateWhenAnimatorEnds;
 
     private final void logf(String fmt, Object... args) {
         Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -508,7 +509,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (mInstantExpanding || !mNotificationsDragEnabled
+        if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled
                 || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
             return false;
         }
@@ -759,14 +760,14 @@
                 if (clearAllExpandHack && !mCancelled) {
                     setExpandedHeightInternal(getMaxPanelHeight());
                 }
-                mHeightAnimator = null;
+                setAnimator(null);
                 if (!mCancelled) {
                     notifyExpandingFinished();
                 }
                 notifyBarPanelExpansionChanged();
             }
         });
-        mHeightAnimator = animator;
+        setAnimator(animator);
         animator.start();
     }
 
@@ -803,15 +804,28 @@
     protected void requestPanelHeightUpdate() {
         float currentMaxPanelHeight = getMaxPanelHeight();
 
-        // If the user isn't actively poking us, let's update the height
-        if ((!mTracking || isTrackingBlocked())
-                && mHeightAnimator == null
-                && !isFullyCollapsed()
-                && currentMaxPanelHeight != mExpandedHeight
-                && mPeekAnimator == null
-                && !mPeekTouching) {
-            setExpandedHeight(currentMaxPanelHeight);
+        if (isFullyCollapsed()) {
+            return;
         }
+
+        if (currentMaxPanelHeight == mExpandedHeight) {
+            return;
+        }
+
+        if (mPeekAnimator != null || mPeekTouching) {
+            return;
+        }
+
+        if (mTracking && !isTrackingBlocked()) {
+            return;
+        }
+
+        if (mHeightAnimator != null) {
+            mPanelUpdateWhenAnimatorEnds = true;
+            return;
+        }
+
+        setExpandedHeight(currentMaxPanelHeight);
     }
 
     public void setExpandedHeightInternal(float h) {
@@ -1063,7 +1077,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (mCancelled) {
-                    mHeightAnimator = null;
+                    setAnimator(null);
                     onAnimationFinished.run();
                 } else {
                     startUnlockHintAnimationPhase2(onAnimationFinished);
@@ -1071,7 +1085,7 @@
             }
         });
         animator.start();
-        mHeightAnimator = animator;
+        setAnimator(animator);
 
         View[] viewsToAnimate = {
                 mKeyguardBottomArea.getIndicationArea(),
@@ -1093,6 +1107,14 @@
         }
     }
 
+    private void setAnimator(ValueAnimator animator) {
+        mHeightAnimator = animator;
+        if (animator == null && mPanelUpdateWhenAnimatorEnds) {
+            mPanelUpdateWhenAnimatorEnds = false;
+            requestPanelHeightUpdate();
+        }
+    }
+
     /**
      * Phase 2: Bounce down.
      */
@@ -1103,13 +1125,13 @@
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                mHeightAnimator = null;
+                setAnimator(null);
                 onAnimationFinished.run();
                 notifyBarPanelExpansionChanged();
             }
         });
         animator.start();
-        mHeightAnimator = animator;
+        setAnimator(animator);
     }
 
     private ValueAnimator createHeightAnimator(float targetHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
index 8cd8791..7633767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
@@ -31,7 +31,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.util.LayoutDirection;
-import android.util.Log;
 
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
@@ -82,6 +81,22 @@
             {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
     };
 
+    // Rounded corners are achieved by arcing a circle of radius `mCornerRadius` from its tangent
+    // points along the curve. On the top and left corners of the triangle, the tangents are as
+    // follows:
+    //      1) Along the straight lines (y = 0 and x = width):
+    //          Ps = R / tan(45)
+    //      2) Along the diagonal line (y = x):
+    //          Pd = √((Ps^2) / 2)
+    //
+    // I.e., the points where we stop the straight lines lie at (starting drawing from the bottom-
+    // right corner and counter-clockwise): (width, height - Radius), (width, Ps), (width - Pd, Pd),
+    // (Pd, height - Pd), (Ps, height), and finally (width - Radius, height).
+    private static final double TAN_THETA = Math.tan(Math.PI / 8.f);
+    private final float mCornerRadius;
+    private final float mCircleOffsetStraight;
+    private final float mCircleOffsetDiag;
+
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final int mDarkModeBackgroundColor;
@@ -113,6 +128,11 @@
         mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);
         mHandler = new Handler();
         setDarkIntensity(0);
+
+        mCornerRadius = context.getResources()
+                .getDimensionPixelSize(R.dimen.stat_sys_mobile_signal_corner_radius);
+        mCircleOffsetStraight = mCornerRadius / (float) TAN_THETA;
+        mCircleOffsetDiag = (float) Math.sqrt(Math.pow(mCircleOffsetStraight, 2.f) / 2.f);
     }
 
     @Override
@@ -204,11 +224,40 @@
         mFullPath.setFillType(FillType.WINDING);
         float width = getBounds().width();
         float height = getBounds().height();
-        float padding = (PAD * width);
-        mFullPath.moveTo(width - padding, height - padding);
-        mFullPath.lineTo(width - padding, padding);
-        mFullPath.lineTo(padding, height - padding);
-        mFullPath.lineTo(width - padding, height - padding);
+        float padding = (int) (PAD * width);  // Stay on pixel boundary
+
+        // 1 - Bottom right, above corner
+        mFullPath.moveTo(width - padding, height - padding - mCornerRadius);
+        // 2 - Line to top right, below corner
+        mFullPath.lineTo(width - padding, padding + mCircleOffsetStraight);
+        // 3 - Arc to top right, on hypotenuse
+        mFullPath.arcTo(
+                width - padding - (2 * mCornerRadius),
+                padding + mCircleOffsetStraight - mCornerRadius,
+                width - padding,
+                padding + mCircleOffsetStraight + mCornerRadius,
+                0.f, -135.f, false
+        );
+        // 4 - Line to bottom left, on hypotenuse
+        mFullPath.lineTo(padding + mCircleOffsetDiag, height - padding - mCircleOffsetDiag);
+        // 5 - Arc to bottom left, on leg
+        mFullPath.arcTo(
+                padding + mCircleOffsetStraight - mCornerRadius,
+                height - padding - (2 * mCornerRadius),
+                padding + mCircleOffsetStraight + mCornerRadius,
+                height - padding,
+                -135.f, -135.f, false
+        );
+        // 6 - Line to bottom rght, before corner
+        mFullPath.lineTo(width - padding - mCornerRadius, height - padding);
+        // 7 - Arc to beginning (bottom right, above corner)
+        mFullPath.arcTo(
+                width - padding - (2 * mCornerRadius),
+                height - padding - (2 * mCornerRadius),
+                width - padding,
+                height - padding,
+                90.f, -90.f, false
+        );
 
         if (mState == STATE_CARRIER_CHANGE) {
             float cutWidth = (DOT_CUT_WIDTH * width);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8ce86ff..7564c82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -49,6 +49,7 @@
 import android.app.RemoteInput;
 import android.app.StatusBarManager;
 import android.app.TaskStackBuilder;
+import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -57,6 +58,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -150,7 +153,6 @@
 import com.android.internal.util.NotificationMessagingUtil;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
-import com.android.keyguard.KeyguardStatusView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
@@ -243,6 +245,8 @@
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.systemui.volume.VolumeComponent;
 
+import com.google.android.colorextraction.ColorExtractor;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -262,7 +266,8 @@
         OnHeadsUpChangedListener, VisualStabilityManager.Callback, CommandQueue.Callbacks,
         ActivatableNotificationView.OnActivatedListener,
         ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
-        ExpandableNotificationRow.OnExpandClickListener, InflationCallback {
+        ExpandableNotificationRow.OnExpandClickListener, InflationCallback,
+        ColorExtractor.OnColorsChangedListener {
     public static final boolean MULTIUSER_DEBUG = false;
 
     public static final boolean ENABLE_REMOTE_INPUT =
@@ -300,7 +305,7 @@
     private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
             = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
     public static final String TAG = "StatusBar";
-    public static final boolean DEBUG = false;
+    public static final boolean DEBUG = true;
     public static final boolean SPEW = false;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
     public static final boolean DEBUG_GESTURES = false;
@@ -426,6 +431,7 @@
     Object mQueueLock = new Object();
 
     protected StatusBarIconController mIconController;
+    private IconManager mIconManager;
 
     // expanded notifications
     protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -444,8 +450,6 @@
 
     // top bar
     protected KeyguardStatusBarView mKeyguardStatusBar;
-    KeyguardStatusView mKeyguardStatusView;
-    KeyguardBottomAreaView mKeyguardBottomArea;
     boolean mLeaveOpenOnKeyguardHide;
     KeyguardIndicationController mKeyguardIndicationController;
 
@@ -512,8 +516,8 @@
                 mUserSetup = userSetup;
                 if (!mUserSetup && mStatusBarView != null)
                     animateCollapseQuickSettings();
-                if (mKeyguardBottomArea != null) {
-                    mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
+                if (mNotificationPanel != null) {
+                    mNotificationPanel.setUserSetupComplete(mUserSetup);
                 }
                 updateQsExpansionEnabled();
             }
@@ -722,6 +726,7 @@
     private KeyguardMonitorImpl mKeyguardMonitor;
     private BatteryController mBatteryController;
     protected boolean mPanelExpanded;
+    private IOverlayManager mOverlayManager;
     private boolean mKeyguardRequested;
     private boolean mIsKeyguard;
     private LogMaker mStatusBarStateLog;
@@ -732,6 +737,7 @@
     private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
     private boolean mClearAllEnabled;
     @Nullable private View mAmbientIndicationContainer;
+    private ColorExtractor mColorExtractor;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -774,6 +780,11 @@
         mAssistManager = Dependency.get(AssistManager.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
+        mOverlayManager = IOverlayManager.Stub.asInterface(
+                ServiceManager.getService(Context.OVERLAY_SERVICE));
+
+        mColorExtractor = Dependency.get(ColorExtractor.class);
+        mColorExtractor.addOnColorsChangedListener(this);
 
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
@@ -970,8 +981,16 @@
             public void onDensityOrFontScaleChanged() {
                 StatusBar.this.onDensityOrFontScaleChanged();
             }
+
+            @Override
+            public void onOverlayChanged() {
+                StatusBar.this.onOverlayChanged();
+            }
         };
         Dependency.get(ConfigurationController.class).addCallback(mConfigurationListener);
+
+        // Make sure that we're using the correct theme
+        onOverlayChanged();
     }
 
     protected void createIconController() {
@@ -1020,8 +1039,8 @@
                 .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                         CollapsedStatusBarFragment.TAG)
                 .commit();
-        Dependency.get(StatusBarIconController.class).addIconGroup(
-                new IconManager((ViewGroup) mKeyguardStatusBar.findViewById(R.id.statusIcons)));
+        mIconManager = new IconManager(mKeyguardStatusBar.findViewById(R.id.statusIcons));
+        Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
         mIconController = Dependency.get(StatusBarIconController.class);
 
         mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager);
@@ -1073,15 +1092,12 @@
             mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
         }
 
-        mKeyguardStatusView =
-                (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
-        mKeyguardBottomArea =
-                (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
         mKeyguardIndicationController =
                 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                 (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
-                mKeyguardBottomArea.getLockIcon());
-        mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
+                mNotificationPanel.getLockIcon());
+        mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);
+
 
         mAmbientIndicationContainer = mStatusBarWindow.findViewById(
                 R.id.ambient_indication_container);
@@ -1134,8 +1150,7 @@
         // Other icons
         mVolumeComponent = getComponent(VolumeComponent.class);
 
-        mKeyguardBottomArea.setStatusBar(this);
-        mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
+        mNotificationPanel.setUserSetupComplete(mUserSetup);
         if (UserManager.get(mContext).isUserSwitcherEnabled()) {
             createUserSwitcher();
         }
@@ -1285,12 +1300,6 @@
         if (mBrightnessMirrorController != null) {
             mBrightnessMirrorController.onDensityOrFontScaleChanged();
         }
-        inflateSignalClusters();
-        mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
-        inflateDismissView();
-        updateClearAll();
-        inflateEmptyShadeView();
-        updateEmptyShadeView();
         mStatusBarKeyguardViewManager.onDensityOrFontScaleChanged();
         // TODO: Bring these out of StatusBar.
         ((UserInfoControllerImpl) Dependency.get(UserInfoController.class))
@@ -1299,6 +1308,44 @@
         if (mKeyguardUserSwitcher != null) {
             mKeyguardUserSwitcher.onDensityOrFontScaleChanged();
         }
+        mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
+
+        reevaluateStyles();
+    }
+
+    protected void onOverlayChanged() {
+        final boolean usingDarkTheme = isUsingDarkTheme();
+        if (DEBUG) {
+            Log.d(TAG, "Updating theme because overlay changed. Is theme dark? " + usingDarkTheme);
+        }
+        reevaluateStyles();
+
+        // Clock and bottom icons
+        mNotificationPanel.onOverlayChanged();
+
+        // Recreate Indication controller because internal references changed
+        // TODO: unregister callbacks before recreating
+        mKeyguardIndicationController =
+                SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
+                        mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
+                        mNotificationPanel.getLockIcon());
+        mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);
+        mKeyguardIndicationController
+                .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
+        mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD);
+        mKeyguardIndicationController.setDozing(mDozing);
+
+        // Top status bar with system icons and clock
+        mKeyguardStatusBar.onOverlayChanged();
+        mIconManager.onOverlayChanged();
+    }
+
+    protected void reevaluateStyles() {
+        inflateSignalClusters();
+        inflateDismissView();
+        updateClearAll();
+        inflateEmptyShadeView();
+        updateEmptyShadeView();
     }
 
     private void updateNotificationsOnDensityOrFontScaleChanged() {
@@ -1347,20 +1394,20 @@
     }
 
     private void inflateEmptyShadeView() {
+        if (mStackScroller == null) {
+            return;
+        }
         mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_no_notifications, mStackScroller, false);
         mStackScroller.setEmptyShadeView(mEmptyShadeView);
     }
 
     private void inflateDismissView() {
-        if (!mClearAllEnabled) {
+        if (!mClearAllEnabled || mStackScroller == null) {
             return;
         }
 
-        // Always inflate with a dark theme, since this sits on the scrim.
-        ContextThemeWrapper themedContext = new ContextThemeWrapper(mContext,
-                style.Theme_DeviceDefault);
-        mDismissView = (DismissView) LayoutInflater.from(themedContext).inflate(
+        mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
         mDismissView.setOnButtonClickListener(new View.OnClickListener() {
             @Override
@@ -1476,10 +1523,8 @@
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mScrimController,
                 mFingerprintUnlockController);
-        mKeyguardIndicationController.setStatusBarKeyguardViewManager(
-                mStatusBarKeyguardViewManager);
-        mKeyguardIndicationController.setUserInfoController(
-                Dependency.get(UserInfoController.class));
+        mKeyguardIndicationController
+                .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
 
@@ -2589,7 +2634,7 @@
 
     public void setQsExpanded(boolean expanded) {
         mStatusBarWindowManager.setQsExpanded(expanded);
-        mKeyguardStatusView.setImportantForAccessibility(expanded
+        mNotificationPanel.setStatusAccessibilityImportance(expanded
                 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
                 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
     }
@@ -2783,8 +2828,20 @@
         return mNotificationPanel.hideStatusBarIconsWhenExpanded();
     }
 
-    public KeyguardIndicationController getKeyguardIndicationController() {
-        return mKeyguardIndicationController;
+    @Override
+    public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
+        updateTheme();
+    }
+
+    public boolean isUsingDarkTheme() {
+        OverlayInfo themeInfo = null;
+        try {
+            themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.dark",
+                    mCurrentUserId);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+        return themeInfo != null && themeInfo.isEnabled();
     }
 
     @Nullable
@@ -4426,6 +4483,7 @@
             mScrimController.setKeyguardShowing(false);
         }
         mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
+        updateTheme();
         updateDozingState();
         updatePublicMode();
         updateStackScrollerState(goingToFullShade, fromShadeLocked);
@@ -4438,6 +4496,35 @@
         Trace.endSection();
     }
 
+    /**
+     * Switches theme from light to dark and vice-versa.
+     */
+    private void updateTheme() {
+        boolean useDarkTheme;
+        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+            useDarkTheme = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK)
+                    .supportsDarkText();
+        } else {
+            useDarkTheme = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM)
+                    .supportsDarkText();
+        }
+
+        // Enable/Disable dark overlay
+        if (isUsingDarkTheme() != useDarkTheme) {
+            if (DEBUG) {
+                Log.d(TAG, "Switching theme to: " + (useDarkTheme ? "Dark" : "Light"));
+            }
+            try {
+                mOverlayManager.setEnabled("com.android.systemui.theme.dark",
+                        useDarkTheme, mCurrentUserId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Can't change theme", e);
+                return;
+            }
+            mStatusBarWindowManager.setKeyguardDark(useDarkTheme);
+        }
+    }
+
     private void updateDozingState() {
         Trace.beginSection("StatusBar#updateDozingState");
         boolean animate = !mDozing && mDozeServiceHost.shouldAnimateWakeup();
@@ -4585,6 +4672,7 @@
         mStackScroller.setStatusBarState(state);
         updateReportRejectedTouchVisibility();
         updateDozing();
+        updateTheme();
         mNotificationShelf.setStatusBarState(state);
     }
 
@@ -4665,8 +4753,12 @@
         return mNavigationBarView;
     }
 
+    /**
+     * TODO: Remove this method. Views should not be passed forward. Will cause theme issues.
+     * @return bottom area view
+     */
     public KeyguardBottomAreaView getKeyguardBottomAreaView() {
-        return mKeyguardBottomArea;
+        return mNotificationPanel.getKeyguardBottomAreaView();
     }
 
     // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
@@ -5020,7 +5112,6 @@
             where.getLocationInWindow(mTmpInt2);
             mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
                     mTmpInt2[1] + where.getHeight() / 2);
-            mNotificationPanel.setTouchDisabled(false);
             mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
             mFalsingManager.onScreenOnFromTouch();
         }
@@ -5177,7 +5268,7 @@
 
         @Override
         public void dozeTimeTick() {
-            mKeyguardStatusView.refreshTime();
+            mNotificationPanel.refreshTime();
         }
 
         @Override
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 a3ef91d..64b21b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -14,7 +14,10 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.ColorInt;
 import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -26,6 +29,7 @@
 import android.widget.LinearLayout.LayoutParams;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBarIconView;
@@ -57,7 +61,6 @@
         return ret;
     }
 
-
     /**
      * Version of ViewGroup that observers state from the DarkIconDispatcher.
      */
@@ -165,6 +168,17 @@
             }
         }
 
+        protected void onOverlayChanged() {
+            @ColorInt int iconColor = Utils.getColorAttr(mContext, R.attr.bgProtectTextColor);
+            for (int i = 0; i < mGroup.getChildCount(); i++) {
+                View child = mGroup.getChildAt(i);
+                if (child instanceof StatusBarIconView) {
+                    StatusBarIconView icon = (StatusBarIconView) child;
+                    icon.setStaticDrawableColor(iconColor);
+                }
+            }
+        }
+
         private void setHeightAndCenter(ImageView imageView, int height) {
             ViewGroup.LayoutParams params = imageView.getLayoutParams();
             params.height = height;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 0326e40..93dc6de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -111,6 +111,18 @@
         mLpChanged.copyFrom(mLp);
     }
 
+    public void setKeyguardDark(boolean dark) {
+        int vis = mStatusBarView.getSystemUiVisibility();
+        if (dark) {
+            vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+            vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+        } else {
+            vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+            vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+        }
+        mStatusBarView.setSystemUiVisibility(vis);
+    }
+
     private void applyKeyguardFlags(State state) {
         if (state.keyguardShowing) {
             mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index f050be4..236e008 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -277,7 +277,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mService.isDozing() && !mService.isPulsing()) {
+        if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {
             // Capture all touch events in always-on.
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index 788fda8..418c48e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -27,5 +27,6 @@
     interface ConfigurationListener {
         default void onConfigChanged(Configuration newConfig) {}
         default void onDensityOrFontScaleChanged() {}
+        default void onOverlayChanged() {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index dc33633..74a30fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -23,6 +23,7 @@
 import android.content.res.TypedArray;
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
@@ -115,4 +116,15 @@
             mLastText = text;
         }
     }
+
+    public void setDatePattern(String pattern) {
+        if (TextUtils.equals(pattern, mDatePattern)) {
+            return;
+        }
+        mDatePattern = pattern;
+        mDateFormat = null;
+        if (isAttachedToWindow()) {
+            updateClock();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index e409b9c..41ef781 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -59,7 +59,7 @@
     private boolean mPanelTracking;
     private boolean mExpansionChanging;
     private boolean mPanelFullWidth;
-    private boolean mPulsing;
+    private boolean mHasPulsingNotifications;
     private boolean mUnlockHintRunning;
 
     public AmbientState(Context context) {
@@ -287,12 +287,12 @@
         mPanelTracking = panelTracking;
     }
 
-    public boolean isPulsing() {
-        return mPulsing;
+    public boolean hasPulsingNotifications() {
+        return mHasPulsingNotifications;
     }
 
-    public void setPulsing(boolean pulsing) {
-        mPulsing = pulsing;
+    public void setHasPulsingNotifications(boolean hasPulsing) {
+        mHasPulsingNotifications = hasPulsing;
     }
 
     public boolean isPanelTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 679d119..84acaf1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -54,7 +54,6 @@
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.OverScroller;
@@ -1946,7 +1945,7 @@
         int numShownItems = 0;
         boolean finish = false;
         int maxDisplayedNotifications = mAmbientState.isDark()
-                ? (isPulsing() ? 1 : 0)
+                ? (hasPulsingNotifications() ? 1 : 0)
                 : mMaxDisplayedNotifications;
 
         for (int i = 0; i < getChildCount(); i++) {
@@ -1955,7 +1954,8 @@
                     && !expandableView.hasNoContentHeight()) {
                 boolean limitReached = maxDisplayedNotifications != -1
                         && numShownItems >= maxDisplayedNotifications;
-                boolean notificationOnAmbientThatIsNotPulsing = isPulsing()
+                boolean notificationOnAmbientThatIsNotPulsing = mAmbientState.isDark()
+                        && hasPulsingNotifications()
                         && expandableView instanceof ExpandableNotificationRow
                         && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
                 if (limitReached || notificationOnAmbientThatIsNotPulsing) {
@@ -2013,7 +2013,7 @@
         return false;
     }
 
-    private boolean isPulsing() {
+    public boolean hasPulsingNotifications() {
         return mPulsing != null;
     }
 
@@ -2225,14 +2225,15 @@
         ActivatableNotificationView firstView = mFirstVisibleBackgroundChild;
         int top = 0;
         if (firstView != null) {
-            int finalTranslationY = (int) ViewState.getFinalTranslationY(firstView);
+            // Round Y up to avoid seeing the background during animation
+            int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
             if (mAnimateNextBackgroundTop
                     || mTopAnimator == null && mCurrentBounds.top == finalTranslationY
                     || mTopAnimator != null && mEndAnimationRect.top == finalTranslationY) {
                 // we're ending up at the same location as we are now, lets just skip the animation
                 top = finalTranslationY;
             } else {
-                top = (int) firstView.getTranslationY();
+                top = (int) Math.ceil(firstView.getTranslationY());
             }
         }
         ActivatableNotificationView lastView =
@@ -2843,7 +2844,7 @@
     }
 
     private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled || isPulsing();
+        boolean running = mAnimationsEnabled || hasPulsingNotifications();
         mShelf.setAnimationsEnabled(running);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2854,7 +2855,7 @@
     }
 
     private void updateAnimationState(View child) {
-        updateAnimationState((mAnimationsEnabled || isPulsing())
+        updateAnimationState((mAnimationsEnabled || hasPulsingNotifications())
                 && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
@@ -4126,7 +4127,7 @@
             return;
         }
         mPulsing = pulsing;
-        mAmbientState.setPulsing(isPulsing());
+        mAmbientState.setHasPulsingNotifications(hasPulsingNotifications());
         updateNotificationAnimationStates();
         updateContentHeight();
         notifyHeightChangeListener(mShelf);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 5717600..8235bc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -416,6 +416,7 @@
                 if (i == 0 && row.isAboveShelf()) {
                     // the first hun can't get off screen.
                     clampHunToMaxTranslation(ambientState, row, childState);
+                    childState.hidden = false;
                 }
             }
             if (row.isPinned()) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
index 15cebc7..8905d72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
@@ -14,13 +14,18 @@
 
 package com.android.systemui;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
 import android.app.Fragment;
+import android.app.Instrumentation;
 import android.support.test.InstrumentationRegistry;
 import android.testing.BaseFragmentTest;
 
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 import com.android.systemui.utils.leaks.LeakCheckedTest.SysuiLeakCheck;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 
@@ -33,6 +38,7 @@
 
     protected final TestableDependency mDependency = new TestableDependency(mContext);
     protected SysuiTestableContext mSysuiContext;
+    private Instrumentation mRealInstrumentation;
 
     public SysuiBaseFragmentTest(Class<? extends Fragment> cls) {
         super(cls);
@@ -44,6 +50,20 @@
         SystemUIFactory.createFromConfig(mContext);
         // TODO: Figure out another way to give reference to a SysuiTestableContext.
         mSysuiContext = (SysuiTestableContext) mContext;
+
+        mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
+        Instrumentation inst = spy(mRealInstrumentation);
+        when(inst.getContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        when(inst.getTargetContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        InstrumentationRegistry.registerInstance(inst, InstrumentationRegistry.getArguments());
+    }
+
+    @After
+    public void SysuiTeardown() {
+        InstrumentationRegistry.registerInstance(mRealInstrumentation,
+                InstrumentationRegistry.getArguments());
     }
 
     @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 9b67529..361a20f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -15,6 +15,10 @@
  */
 package com.android.systemui;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Instrumentation;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -24,6 +28,7 @@
 import android.testing.LeakCheck;
 import android.util.Log;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 
@@ -42,11 +47,26 @@
     public SysuiTestableContext mContext = new SysuiTestableContext(
             InstrumentationRegistry.getContext(), getLeakCheck());
     public TestableDependency mDependency = new TestableDependency(mContext);
+    private Instrumentation mRealInstrumentation;
 
     @Before
     public void SysuiSetup() throws Exception {
         System.setProperty("dexmaker.share_classloader", "true");
         SystemUIFactory.createFromConfig(mContext);
+
+        mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
+        Instrumentation inst = spy(mRealInstrumentation);
+        when(inst.getContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        when(inst.getTargetContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        InstrumentationRegistry.registerInstance(inst, InstrumentationRegistry.getArguments());
+    }
+
+    @After
+    public void SysuiTeardown() {
+        InstrumentationRegistry.registerInstance(mRealInstrumentation,
+                InstrumentationRegistry.getArguments());
     }
 
     protected LeakCheck getLeakCheck() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 6380847..b6827ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -232,6 +232,17 @@
     }
 
     @Test
+    public void testBindNotification_UnblockablePackageDoesNotUseChannelName() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                mNotificationChannel.getImportance(), mSbn, null, null, null,
+                null, Collections.singleton(TEST_PACKAGE_NAME));
+        final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(mContext.getString(R.string.notification_header_default_channel),
+                textView.getText());
+    }
+
+    @Test
     public void testBindNotification_DefaultChannelUsesNameWhenMoreThanOneChannelExists()
             throws Exception {
         when(mMockINotificationManager.getNumNotificationChannelsForPackage(
@@ -332,6 +343,21 @@
     }
 
     @Test
+    public void testBindNotification_SettingsTextWithMultipleChannelsForUnblockableApp()
+            throws Exception {
+        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
+                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(2);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                mNotificationChannel.getImportance(), mSbn,
+                (View v, NotificationChannel c, int appUid) -> {
+                }, null, null, null, Collections.singleton(TEST_PACKAGE_NAME));
+        final TextView settingsButton =
+                (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+        assertEquals(getStringById(R.string.notification_more_settings), settingsButton.getText());
+    }
+
+    @Test
     public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -502,6 +528,19 @@
     }
 
     @Test
+    public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                mNotificationChannel.getImportance(), mSbn, null, null, null,
+                null, Collections.singleton(TEST_PACKAGE_NAME));
+        final TextView numChannelsView =
+                (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
+        assertEquals(View.VISIBLE, numChannelsView.getVisibility());
+        assertEquals(mContext.getString(R.string.notification_unblockable_desc),
+                numChannelsView.getText());
+    }
+
+    @Test
     @UiThreadTest
     public void testBindNotification_ChannelDisabledTextShowsForDefaultChannel()
             throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SignalClusterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SignalClusterViewTest.java
new file mode 100644
index 0000000..28a5aa3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SignalClusterViewTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.telephony.SubscriptionInfo;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.NetworkController.IconState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class SignalClusterViewTest extends SysuiTestCase {
+
+    private SignalClusterView mSignalCluster;
+
+    @Before
+    public void setup() {
+        mSignalCluster = (SignalClusterView) LayoutInflater.from(mContext)
+                .inflate(R.layout.signal_cluster_view, null);
+    }
+
+    @Test
+    public void testNonDefaultSim() {
+        SubscriptionInfo first = mock(SubscriptionInfo.class);
+        SubscriptionInfo second = mock(SubscriptionInfo.class);
+        when(first.getSubscriptionId()).thenReturn(0);
+        when(second.getSubscriptionId()).thenReturn(1);
+        mSignalCluster.setSubs(Arrays.asList(first, second));
+        mSignalCluster.setQsSignalCluster();
+        mSignalCluster.setMobileDataIndicators(new IconState(true, 0, 0, ""), null, 0, 0,
+                false, false, "", "", false, 1, false);
+    }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
index 9b7c597..d925364 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
@@ -41,9 +41,7 @@
 
     @Before
     public void setUp() {
-        Context context = InstrumentationRegistry.getContext();
-
-        mInner = WakeLock.createPartialInner(context, WakeLockTest.class.getName());
+        mInner = WakeLock.createPartialInner(mContext, WakeLockTest.class.getName());
         mWakeLock = WakeLock.wrap(mInner);
     }
 
diff --git a/packages/SysuiDarkThemeOverlay/Android.mk b/packages/SysuiDarkThemeOverlay/Android.mk
new file mode 100644
index 0000000..4b83058
--- /dev/null
+++ b/packages/SysuiDarkThemeOverlay/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := SysuiDarkTheme
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := SysuiDarkThemeOverlay
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/SysuiDarkThemeOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..ba1c91c
--- /dev/null
+++ b/packages/SysuiDarkThemeOverlay/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.systemui.theme.dark"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <overlay android:targetPackage="android" android:priority="1"/>
+
+    <application android:label="@string/sysui_overlay_dark" android:hasCode="false"/>
+</manifest>
diff --git a/packages/SysuiDarkThemeOverlay/res/values/strings.xml b/packages/SysuiDarkThemeOverlay/res/values/strings.xml
new file mode 100644
index 0000000..71f48d6
--- /dev/null
+++ b/packages/SysuiDarkThemeOverlay/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="sysui_overlay_dark">Dark</string>
+
+</resources>
+
diff --git a/packages/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml b/packages/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
new file mode 100644
index 0000000..28ecfa0
--- /dev/null
+++ b/packages/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Dark theme for a window that should look like the Settings app.  -->
+    <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
+        <!-- Color palette -->
+        <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
+        <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
+        <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+        <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+        <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
+        <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
+        <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
+        <item name="android:colorBackgroundFloating">#000</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ddc9e6c..96f1d64 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3962,6 +3962,16 @@
     // OS: O
     APP_TRANSITION_BIND_APPLICATION_DELAY_MS = 945;
 
+    // FIELD - The group ID of a notification.
+    // Type: string
+    // OS: O
+    FIELD_NOTIFICATION_GROUP_ID = 946;
+
+    // FIELD - If the notification is a group summary: 1.
+    // Type: int encoded boolean
+    // OS: O
+    FIELD_NOTIFICATION_GROUP_SUMMARY = 947;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // OPEN: Settings > System > Languages & input > Advanced > Lift to open camera
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e5c3106..5a7f6e3 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -352,7 +352,7 @@
         AudioSystem.STREAM_MUSIC,           // STREAM_TTS
         AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
     };
-    private int[] mStreamVolumeAlias;
+    protected static int[] mStreamVolumeAlias;
 
     /**
      * Map AudioSystem.STREAM_* constants to app ops.  This should be used
@@ -1817,7 +1817,7 @@
     }
 
     // UI update and Broadcast Intent
-    private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
+    protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
         streamType = mStreamVolumeAlias[streamType];
 
         if (streamType == AudioSystem.STREAM_MUSIC) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 9767e72..78184fa 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -18,7 +18,13 @@
 
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
 import static com.android.server.ConnectivityService.SHORT_ARG;
 
@@ -805,48 +811,80 @@
         }
 
         private void handleWifiApAction(Intent intent) {
-            final int curState =  intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+            final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+            final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
+            final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
+
             synchronized (Tethering.this.mPublicSync) {
                 switch (curState) {
                     case WifiManager.WIFI_AP_STATE_ENABLING:
                         // We can see this state on the way to both enabled and failure states.
                         break;
                     case WifiManager.WIFI_AP_STATE_ENABLED:
-                        // When the AP comes up and we've been requested to tether it, do so.
-                        // Otherwise, assume it's a local-only hotspot request.
-                        final int state = mWifiTetherRequested
-                                ? IControlsTethering.STATE_TETHERED
-                                : IControlsTethering.STATE_LOCAL_ONLY;
-                        tetherMatchingInterfaces(state, ConnectivityManager.TETHERING_WIFI);
+                        enableWifiIpServingLocked(ifname, ipmode);
                         break;
                     case WifiManager.WIFI_AP_STATE_DISABLED:
                     case WifiManager.WIFI_AP_STATE_DISABLING:
                     case WifiManager.WIFI_AP_STATE_FAILED:
                     default:
-                        if (DBG) {
-                            Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
-                                curState);
-                        }
-                        // Tell appropriate interface state machines that they should tear
-                        // themselves down.
-                        for (int i = 0; i < mTetherStates.size(); i++) {
-                            TetherInterfaceStateMachine tism =
-                                    mTetherStates.valueAt(i).stateMachine;
-                            if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
-                                tism.sendMessage(
-                                        TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
-                                break;  // There should be at most one of these.
-                            }
-                        }
-                        // Regardless of whether we requested this transition, the AP has gone
-                        // down.  Don't try to tether again unless we're requested to do so.
-                        mWifiTetherRequested = false;
-                    break;
+                        disableWifiIpServingLocked(curState);
+                        break;
                 }
             }
         }
     }
 
+    // TODO: Pass in the interface name and, if non-empty, only turn down IP
+    // serving on that one interface.
+    private void disableWifiIpServingLocked(int apState) {
+        if (DBG) Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + apState);
+
+        // Tell appropriate interface state machines that they should tear
+        // themselves down.
+        for (int i = 0; i < mTetherStates.size(); i++) {
+            TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
+            if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
+                tism.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
+                break;  // There should be at most one of these.
+            }
+        }
+        // Regardless of whether we requested this transition, the AP has gone
+        // down.  Don't try to tether again unless we're requested to do so.
+        mWifiTetherRequested = false;
+    }
+
+    private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
+        // Map wifiIpMode values to IControlsTethering serving states, inferring
+        // from mWifiTetherRequested as a final "best guess".
+        final int ipServingMode;
+        switch (wifiIpMode) {
+            case IFACE_IP_MODE_TETHERED:
+                ipServingMode = IControlsTethering.STATE_TETHERED;
+                break;
+            case IFACE_IP_MODE_LOCAL_ONLY:
+                ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
+                break;
+            default:
+                // Resort to legacy "guessing" behaviour.
+                //
+                // When the AP comes up and we've been requested to tether it,
+                // do so. Otherwise, assume it's a local-only hotspot request.
+                //
+                // TODO: Once all AP broadcasts are known to include ifname and
+                // mode information delete this code path and log an error.
+                ipServingMode = mWifiTetherRequested
+                        ? IControlsTethering.STATE_TETHERED
+                        : IControlsTethering.STATE_LOCAL_ONLY;
+                break;
+        }
+
+        if (!TextUtils.isEmpty(ifname)) {
+            changeInterfaceState(ifname, ipServingMode);
+        } else {
+            tetherMatchingInterfaces(ipServingMode, ConnectivityManager.TETHERING_WIFI);
+        }
+    }
+
     // TODO: Consider renaming to something more accurate in its description.
     // This method:
     //     - allows requesting either tethering or local hotspot serving states
@@ -879,22 +917,26 @@
             return;
         }
 
+        changeInterfaceState(chosenIface, requestedState);
+    }
+
+    private void changeInterfaceState(String ifname, int requestedState) {
         final int result;
         switch (requestedState) {
             case IControlsTethering.STATE_UNAVAILABLE:
             case IControlsTethering.STATE_AVAILABLE:
-                result = untether(chosenIface);
+                result = untether(ifname);
                 break;
             case IControlsTethering.STATE_TETHERED:
             case IControlsTethering.STATE_LOCAL_ONLY:
-                result = tether(chosenIface, requestedState);
+                result = tether(ifname, requestedState);
                 break;
             default:
                 Log.wtf(TAG, "Unknown interface state: " + requestedState);
                 return;
         }
         if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-            Log.e(TAG, "unable start or stop tethering on iface " + chosenIface);
+            Log.e(TAG, "unable start or stop tethering on iface " + ifname);
             return;
         }
     }
@@ -1377,10 +1419,10 @@
                 final String iface = who.interfaceName();
                 switch (mode) {
                     case IControlsTethering.STATE_TETHERED:
-                        mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_TETHERED);
+                        mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
                         break;
                     case IControlsTethering.STATE_LOCAL_ONLY:
-                        mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
+                        mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
                         break;
                     default:
                         Log.wtf(TAG, "Unknown active serving mode: " + mode);
@@ -1398,7 +1440,7 @@
             if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
                 if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                     getWifiManager().updateInterfaceIpState(
-                            who.interfaceName(), WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
+                            who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java
index 6902b1a..ffee99f 100644
--- a/services/core/java/com/android/server/display/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/DisplayTransformManager.java
@@ -21,6 +21,7 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.util.MathUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -48,6 +49,10 @@
      */
     public static final int LEVEL_COLOR_MATRIX_INVERT_COLOR = 300;
 
+    private static final int SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX = 1015;
+    private static final int SURFACE_FLINGER_TRANSACTION_DALTONIZER = 1014;
+    private static final int SURFACE_FLINGER_TRANSACTION_SATURATION = 1022;
+
     /**
      * Map of level -> color transformation matrix.
      */
@@ -66,6 +71,10 @@
     @GuardedBy("mDaltonizerModeLock")
     private int mDaltonizerMode = -1;
 
+    private final Object mSaturationLock = new Object();
+    @GuardedBy("mSaturationLock")
+    private float mSaturation = 1.0f;
+
     /* package */ DisplayTransformManager() {
     }
 
@@ -156,6 +165,30 @@
     }
 
     /**
+     * Returns the current saturation.
+     */
+    public float getSaturation() {
+        synchronized (mSaturationLock) {
+            return mSaturation;
+        }
+    }
+
+    /**
+     * Sets the saturation level of the display. The default value is 1.0.
+     *
+     * @param saturation A value between 0 (0% saturation, grayscale) and 2 (100% extra saturation)
+     */
+    public void setSaturation(float saturation) {
+        synchronized (mSaturationLock) {
+            saturation = MathUtils.constrain(saturation, 0.0f, 2.0f);
+            if (mSaturation != saturation) {
+                mSaturation = saturation;
+                applySaturation(saturation);
+            }
+        }
+    }
+
+    /**
      * Propagates the provided color transformation matrix to the SurfaceFlinger.
      */
     private static void applyColorMatrix(float[] m) {
@@ -172,7 +205,7 @@
                 data.writeInt(0);
             }
             try {
-                flinger.transact(1015, data, null, 0);
+                flinger.transact(SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX, data, null, 0);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Failed to set color transform", ex);
             } finally {
@@ -191,7 +224,7 @@
             data.writeInterfaceToken("android.ui.ISurfaceComposer");
             data.writeInt(mode);
             try {
-                flinger.transact(1014, data, null, 0);
+                flinger.transact(SURFACE_FLINGER_TRANSACTION_DALTONIZER, data, null, 0);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Failed to set Daltonizer mode", ex);
             } finally {
@@ -199,4 +232,23 @@
             }
         }
     }
+
+    /**
+     * Propagates the provided saturation to the SurfaceFlinger.
+     */
+    private static void applySaturation(float saturation) {
+        final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+        if (flinger != null) {
+            final Parcel data = Parcel.obtain();
+            data.writeInterfaceToken("android.ui.ISurfaceComposer");
+            data.writeFloat(saturation);
+            try {
+                flinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to set saturation", ex);
+            } finally {
+                data.recycle();
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index d574265..b3cf57b 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -285,12 +285,6 @@
         if (mIsActivated == null || mIsActivated != activated) {
             Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
 
-            if (mIsActivated != null) {
-                Secure.putLongForUser(getContext().getContentResolver(),
-                        Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
-                        mCurrentUser);
-            }
-
             mIsActivated = activated;
 
             if (mAutoMode != null) {
@@ -430,19 +424,6 @@
         outTemp[10] = blue;
     }
 
-    private Calendar getLastActivatedTime() {
-        final ContentResolver cr = getContext().getContentResolver();
-        final long lastActivatedTimeMillis = Secure.getLongForUser(
-                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mCurrentUser);
-        if (lastActivatedTimeMillis < 0) {
-            return null;
-        }
-
-        final Calendar lastActivatedTime = Calendar.getInstance();
-        lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
-        return lastActivatedTime;
-    }
-
     private abstract class AutoMode implements NightDisplayController.Callback {
         public abstract void onStart();
 
@@ -522,7 +503,7 @@
             mStartTime = mController.getCustomStartTime();
             mEndTime = mController.getCustomEndTime();
 
-            mLastActivatedTime = getLastActivatedTime();
+            mLastActivatedTime = mController.getLastActivatedTime();
 
             // Force an update to initialize state.
             updateActivated();
@@ -538,7 +519,7 @@
 
         @Override
         public void onActivated(boolean activated) {
-            mLastActivatedTime = getLastActivatedTime();
+            mLastActivatedTime = mController.getLastActivatedTime();
             updateNextAlarm(activated, Calendar.getInstance());
         }
 
@@ -579,7 +560,7 @@
             }
 
             boolean activate = state.isNight();
-            final Calendar lastActivatedTime = getLastActivatedTime();
+            final Calendar lastActivatedTime = mController.getLastActivatedTime();
             if (lastActivatedTime != null) {
                 final Calendar now = Calendar.getInstance();
                 final Calendar sunrise = state.sunrise();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 321b660..fe2c5bd 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -139,6 +139,7 @@
 
     private static final int PROFILE_KEY_IV_SIZE = 12;
     private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
+    private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
 
     // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
     private final Object mSeparateChallengeLock = new Object();
@@ -1977,14 +1978,16 @@
         }
         long handle = getSyntheticPasswordHandleLocked(userId);
         // This is a global setting
-        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
+        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
+                SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
       return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
     }
 
     private boolean shouldMigrateToSyntheticPasswordLocked(int userId) throws RemoteException {
         long handle = getSyntheticPasswordHandleLocked(userId);
         // This is a global setting
-        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
+        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
+                SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
         return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
     }
 
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index d1fb28a..d730c56 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -71,7 +71,7 @@
                     runClear();
                     break;
                 case COMMAND_SP:
-                    runEnableSp();
+                    runChangeSp();
                     break;
                 case COMMAND_SET_DISABLED:
                     runSetDisabled();
@@ -107,10 +107,15 @@
         mNew = getNextArg();
     }
 
-    private void runEnableSp() {
-        if (mNew != null) {
-            mLockPatternUtils.enableSyntheticPassword();
-            getOutPrintWriter().println("Synthetic password enabled");
+    private void runChangeSp() {
+        if (mNew != null ) {
+            if ("1".equals(mNew)) {
+                mLockPatternUtils.enableSyntheticPassword();
+                getOutPrintWriter().println("Synthetic password enabled");
+            } else if ("0".equals(mNew)) {
+                mLockPatternUtils.disableSyntheticPassword();
+                getOutPrintWriter().println("Synthetic password disabled");
+            }
         }
         getOutPrintWriter().println(String.format("SP Enabled = %b",
                 mLockPatternUtils.isSyntheticPasswordEnabled()));
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b630368..41682eb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1051,7 +1051,8 @@
     @VisibleForTesting
     void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
             LightsManager lightsManager, NotificationListeners notificationListeners,
-            ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper) {
+            ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
+            NotificationUsageStats usageStats) {
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                 Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1074,7 +1075,7 @@
         } catch (Resources.NotFoundException e) {
             extractorNames = new String[0];
         }
-        mUsageStats = new NotificationUsageStats(getContext());
+        mUsageStats = usageStats;
         mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
         mRankingHelper = new RankingHelper(getContext(),
                 getContext().getPackageManager(),
@@ -1243,7 +1244,7 @@
 
         init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
                 getLocalService(LightsManager.class), new NotificationListeners(),
-                null, snoozeHelper);
+                null, snoozeHelper, new NotificationUsageStats(getContext()));
         publishBinderService(Context.NOTIFICATION_SERVICE, mService);
         publishLocalService(NotificationManagerInternal.class, mInternalService);
     }
@@ -2775,7 +2776,7 @@
         if (n == null) {
             return;
         }
-        n.sbn.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
+        n.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
         EventLogTags.writeNotificationAutogrouped(key);
     }
 
@@ -2784,7 +2785,7 @@
         if (n == null) {
             return;
         }
-        n.sbn.setOverrideGroupKey(null);
+        n.setOverrideGroupKey(null);
         EventLogTags.writeNotificationUnautogrouped(key);
     }
 
@@ -3714,7 +3715,7 @@
                     if (!mInCall && hasValidVibrate && !ringerModeSilent) {
                         mVibrateNotificationKey = key;
 
-                        buzz = playVibration(record, vibration);
+                        buzz = playVibration(record, vibration, hasValidSound);
                     }
                 }
             }
@@ -3788,22 +3789,41 @@
         return false;
     }
 
-    private boolean playVibration(final NotificationRecord record, long[] vibration) {
+    private boolean playVibration(final NotificationRecord record, long[] vibration,
+            boolean delayVibForSound) {
         // Escalate privileges so we can use the vibrator even if the
         // notifying app does not have the VIBRATE permission.
         long identity = Binder.clearCallingIdentity();
         try {
-            final boolean insistent =
-                (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0;
-            final VibrationEffect effect = VibrationEffect.createWaveform(
-                    vibration, insistent ? 0 : -1 /*repeatIndex*/);
-            mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
-                    effect, record.getAudioAttributes());
+            final VibrationEffect effect;
+            try {
+                final boolean insistent =
+                        (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0;
+                effect = VibrationEffect.createWaveform(
+                        vibration, insistent ? 0 : -1 /*repeatIndex*/);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Error creating vibration waveform with pattern: " +
+                        Arrays.toString(vibration));
+                return false;
+            }
+            if (delayVibForSound) {
+                new Thread(() -> {
+                    // delay the vibration by the same amount as the notification sound
+                    final int waitMs = mAudioManager.getFocusRampTimeMs(
+                            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+                            record.getAudioAttributes());
+                    if (DBG) Slog.v(TAG, "Delaying vibration by " + waitMs + "ms");
+                    try {
+                        Thread.sleep(waitMs);
+                    } catch (InterruptedException e) { }
+                    mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                            effect, record.getAudioAttributes());
+                }).start();
+            } else {
+                mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                        effect, record.getAudioAttributes());
+            }
             return true;
-        } catch (IllegalArgumentException e) {
-            Slog.e(TAG, "Error creating vibration waveform with pattern: " +
-                    Arrays.toString(vibration));
-            return false;
         } finally{
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 95e1db7..f3ae67e 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -73,6 +73,7 @@
 public final class NotificationRecord {
     static final String TAG = "NotificationRecord";
     static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int MAX_LOGTAG_LENGTH = 35;
     final StatusBarNotification sbn;
     final int mOriginalFlags;
     private final Context mContext;
@@ -127,6 +128,8 @@
     private boolean mShowBadge;
     private LogMaker mLogMaker;
     private Light mLight;
+    private String mGroupLogTag;
+    private String mChannelIdLogTag;
 
     @VisibleForTesting
     public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -749,6 +752,37 @@
         return sbn.getGroupKey();
     }
 
+    public void setOverrideGroupKey(String overrideGroupKey) {
+        sbn.setOverrideGroupKey(overrideGroupKey);
+        mGroupLogTag = null;
+    }
+
+    private String getGroupLogTag() {
+        if (mGroupLogTag == null) {
+            mGroupLogTag = shortenTag(sbn.getGroup());
+        }
+        return mGroupLogTag;
+    }
+
+    private String getChannelIdLogTag() {
+        if (mChannelIdLogTag == null) {
+            mChannelIdLogTag = shortenTag(mChannel.getId());
+        }
+        return mChannelIdLogTag;
+    }
+
+    private String shortenTag(String longTag) {
+        if (longTag == null) {
+            return null;
+        }
+        if (longTag.length() < MAX_LOGTAG_LENGTH) {
+            return longTag;
+        } else {
+            return longTag.substring(0, MAX_LOGTAG_LENGTH - 8) + "-" +
+                    Integer.toHexString(longTag.hashCode());
+        }
+    }
+
     public boolean isImportanceFromUser() {
         return mImportance == mUserImportance;
     }
@@ -806,16 +840,23 @@
 
     public LogMaker getLogMaker(long now) {
         if (mLogMaker == null) {
+            // initialize fields that only change on update (so a new record)
             mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
                     .setPackageName(sbn.getPackageName())
                     .addTaggedData(MetricsEvent.NOTIFICATION_ID, sbn.getId())
-                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag());
+                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag())
+                    .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag());
         }
+        // reset fields that can change between updates, or are used by multiple logs
         return mLogMaker
                 .clearCategory()
                 .clearType()
                 .clearSubtype()
                 .clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag())
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY,
+                        sbn.getNotification().isGroupSummary() ? 1 : 0)
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now));
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3ca68de..8bd1f79 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3594,13 +3594,14 @@
 
     @Override
     public void checkPackageStartable(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
         final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (ps == null) {
+            if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) {
                 throw new SecurityException("Package " + packageName + " was not found!");
             }
 
@@ -3869,15 +3870,26 @@
 
     @Override
     public String[] currentToCanonicalPackageNames(String[] names) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return names;
         }
-        String[] out = new String[names.length];
+        final String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
             for (int i=names.length-1; i>=0; i--) {
-                PackageSetting ps = mSettings.mPackages.get(names[i]);
-                out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
+                final PackageSetting ps = mSettings.mPackages.get(names[i]);
+                boolean translateName = false;
+                if (ps != null && ps.realName != null) {
+                    final boolean targetIsInstantApp = ps.getInstantApp(callingUserId);
+                    translateName = !targetIsInstantApp
+                            || canViewInstantApps
+                            || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+                                    UserHandle.getAppId(callingUid), ps.appId);
+                }
+                out[i] = translateName ? ps.realName : names[i];
             }
         }
         return out;
@@ -3885,15 +3897,28 @@
 
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return names;
         }
-        String[] out = new String[names.length];
+        final String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
             for (int i=names.length-1; i>=0; i--) {
-                String cur = mSettings.getRenamedPackageLPr(names[i]);
-                out[i] = cur != null ? cur : names[i];
+                final String cur = mSettings.getRenamedPackageLPr(names[i]);
+                boolean translateName = false;
+                if (cur != null) {
+                    final PackageSetting ps = mSettings.mPackages.get(names[i]);
+                    final boolean targetIsInstantApp =
+                            ps != null && ps.getInstantApp(callingUserId);
+                    translateName = !targetIsInstantApp
+                            || canViewInstantApps
+                            || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+                                    UserHandle.getAppId(callingUid), ps.appId);
+                }
+                out[i] = translateName ? cur : names[i];
             }
         }
         return out;
@@ -5303,12 +5328,13 @@
             Log.e(TAG, "No such user:" + userId);
             return;
         }
+        final int callingUid = Binder.getCallingUid();
 
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                 "grantRuntimePermission");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "grantRuntimePermission");
 
@@ -5320,11 +5346,18 @@
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
-
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
+            sb = (SettingBase) pkg.mExtras;
+            if (sb == null) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
+            if (sb instanceof PackageSetting
+                    && filterAppAccessLPr((PackageSetting) sb, callingUid, userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
 
             enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
 
@@ -5339,10 +5372,6 @@
             }
 
             uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
-            sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
 
             final PermissionsState permissionsState = sb.getPermissionsState();
 
@@ -5612,7 +5641,8 @@
 
         enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getPermissionFlags");
 
@@ -5621,17 +5651,18 @@
             if (pkg == null) {
                 return 0;
             }
-
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 return 0;
             }
-
-            SettingBase sb = (SettingBase) pkg.mExtras;
+            final SettingBase sb = (SettingBase) pkg.mExtras;
             if (sb == null) {
                 return 0;
             }
-
+            if (sb instanceof PackageSetting
+                    && filterAppAccessLPr((PackageSetting) sb, callingUid, userId)) {
+                return 0;
+            }
             PermissionsState permissionsState = sb.getPermissionsState();
             return permissionsState.getPermissionFlags(name, userId);
         }
@@ -6172,7 +6203,8 @@
 
     @Override
     public int getFlagsForUid(int uid) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
         synchronized (mPackages) {
@@ -6182,6 +6214,9 @@
                 return sus.pkgFlags;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return 0;
+                }
                 return ps.pkgFlags;
             }
         }
@@ -6190,7 +6225,8 @@
 
     @Override
     public int getPrivateFlagsForUid(int uid) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
         synchronized (mPackages) {
@@ -6200,6 +6236,9 @@
                 return sus.pkgPrivateFlags;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return 0;
+                }
                 return ps.pkgPrivateFlags;
             }
         }
@@ -8049,13 +8088,14 @@
 
     @Override
     public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get installed packages");
 
@@ -8065,9 +8105,12 @@
             if (listUninstalled) {
                 list = new ArrayList<>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                         continue;
                     }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                        return null;
+                    }
                     final PackageInfo pi = generatePackageInfo(ps, flags, userId);
                     if (pi != null) {
                         list.add(pi);
@@ -8076,10 +8119,13 @@
             } else {
                 list = new ArrayList<>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
-                    if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                            Binder.getCallingUid(), userId, flags)) {
+                    final PackageSetting ps = (PackageSetting) p.mExtras;
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                         continue;
                     }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                        return null;
+                    }
                     final PackageInfo pi = generatePackageInfo((PackageSetting)
                             p.mExtras, flags, userId);
                     if (pi != null) {
@@ -8166,7 +8212,8 @@
 
     @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -8185,9 +8232,12 @@
                         effectiveFlags |= PackageManager.MATCH_ANY_USER;
                     }
                     if (ps.pkg != null) {
-                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                        if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                             continue;
                         }
+                        if (filterAppAccessLPr(ps, callingUid, userId)) {
+                            return null;
+                        }
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
@@ -8198,7 +8248,7 @@
                         // Shared lib filtering done in generateApplicationInfoFromSettingsLPw
                         // and already converts to externally visible package name
                         ai = generateApplicationInfoFromSettingsLPw(ps.name,
-                                Binder.getCallingUid(), effectiveFlags, userId);
+                                callingUid, effectiveFlags, userId);
                     }
                     if (ai != null) {
                         list.add(ai);
@@ -8212,6 +8262,9 @@
                         if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                             continue;
                         }
+                        if (filterAppAccessLPr(ps, callingUid, userId)) {
+                            return null;
+                        }
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
@@ -9404,6 +9457,11 @@
     @Override
     public boolean performDexOpt(String packageName,
             boolean checkProfiles, int compileReason, boolean force, boolean bootComplete) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
+        }
         int dexoptStatus = performDexOptWithStatus(
               packageName, checkProfiles, compileReason, force, bootComplete);
         return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
@@ -9427,6 +9485,8 @@
             boolean bootComplete) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
         }
         int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
                 targetCompilerFilter, force, bootComplete);
@@ -9526,6 +9586,8 @@
             boolean force) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
         }
         mDexManager.reconcileSecondaryDexFiles(packageName);
         return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
@@ -14422,19 +14484,23 @@
     @Override
     public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getApplicationHidden for user " + userId);
-        PackageSetting pkgSetting;
+        PackageSetting ps;
         long callingId = Binder.clearCallingIdentity();
         try {
             // writer
             synchronized (mPackages) {
-                pkgSetting = mSettings.mPackages.get(packageName);
-                if (pkgSetting == null) {
+                ps = mSettings.mPackages.get(packageName);
+                if (ps == null) {
                     return true;
                 }
-                return pkgSetting.getHidden(userId);
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return true;
+                }
+                return ps.getHidden(userId);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -14450,8 +14516,8 @@
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
                 null);
         PackageSetting pkgSetting;
-        final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "installExistingPackage for user " + userId);
         if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
@@ -14934,10 +15000,16 @@
 
     @Override
     public int getIntentVerificationStatus(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
         }
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+            }
             return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
         }
     }
@@ -14960,10 +15032,15 @@
     @Override
     public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
             String packageName) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return ParceledListSlice.emptyList();
+            }
             return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
         }
     }
@@ -17129,12 +17206,15 @@
 
     @Override
     public List<String> getPreviousCodePaths(String packageName) {
+        final int callingUid = Binder.getCallingUid();
         final List<String> result = new ArrayList<>();
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        if (getInstantAppPackageName(callingUid) != null) {
             return result;
         }
         final PackageSetting ps = mSettings.mPackages.get(packageName);
-        if (ps != null && ps.oldCodePaths != null) {
+        if (ps != null
+                && ps.oldCodePaths != null
+                && !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
             result.addAll(ps.oldCodePaths);
         }
         return result;
@@ -18364,8 +18444,11 @@
     @Override
     public void deletePackageVersioned(VersionedPackage versionedPackage,
             final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
+        final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_PACKAGES, null);
+        final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_INSTANT_APPS);
         Preconditions.checkNotNull(versionedPackage);
         Preconditions.checkNotNull(observer);
         Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
@@ -18430,33 +18513,45 @@
             public void run() {
                 mHandler.removeCallbacks(this);
                 int returnCode;
-                if (!deleteAllUsers) {
-                    returnCode = deletePackageX(internalPackageName, versionCode,
-                            userId, deleteFlags);
-                } else {
-                    int[] blockUninstallUserIds = getBlockUninstallForUsers(
-                            internalPackageName, users);
-                    // If nobody is blocking uninstall, proceed with delete for all users
-                    if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
+                boolean doDeletePackage = true;
+                if (ps != null) {
+                    final boolean targetIsInstantApp =
+                            ps.getInstantApp(UserHandle.getUserId(callingUid));
+                    doDeletePackage = !targetIsInstantApp
+                            || hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
+                }
+                if (doDeletePackage) {
+                    if (!deleteAllUsers) {
                         returnCode = deletePackageX(internalPackageName, versionCode,
                                 userId, deleteFlags);
                     } else {
-                        // Otherwise uninstall individually for users with blockUninstalls=false
-                        final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
-                        for (int userId : users) {
-                            if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
-                                returnCode = deletePackageX(internalPackageName, versionCode,
-                                        userId, userFlags);
-                                if (returnCode != PackageManager.DELETE_SUCCEEDED) {
-                                    Slog.w(TAG, "Package delete failed for user " + userId
-                                            + ", returnCode " + returnCode);
+                        int[] blockUninstallUserIds = getBlockUninstallForUsers(
+                                internalPackageName, users);
+                        // If nobody is blocking uninstall, proceed with delete for all users
+                        if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                            returnCode = deletePackageX(internalPackageName, versionCode,
+                                    userId, deleteFlags);
+                        } else {
+                            // Otherwise uninstall individually for users with blockUninstalls=false
+                            final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
+                            for (int userId : users) {
+                                if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
+                                    returnCode = deletePackageX(internalPackageName, versionCode,
+                                            userId, userFlags);
+                                    if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+                                        Slog.w(TAG, "Package delete failed for user " + userId
+                                                + ", returnCode " + returnCode);
+                                    }
                                 }
                             }
+                            // The app has only been marked uninstalled for certain users.
+                            // We still need to report that delete was blocked
+                            returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
                         }
-                        // The app has only been marked uninstalled for certain users.
-                        // We still need to report that delete was blocked
-                        returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
                     }
+                } else {
+                    returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
                 }
                 try {
                     observer.onPackageDeleted(packageName, returnCode, null);
@@ -19267,6 +19362,10 @@
     @Override
     public boolean getBlockUninstallForUser(String packageName, int userId) {
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                return true;
+            }
             return mSettings.getBlockUninstallLPr(userId, packageName);
         }
     }
@@ -19616,9 +19715,14 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */, "clear application data");
 
+        final PackageSetting ps = mSettings.getPackageLPr(packageName);
+        if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+            return;
+        }
         if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
             throw new SecurityException("Cannot clear data for a protected package: "
                     + packageName);
@@ -19876,11 +19980,14 @@
     @Override
     public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
             final IPackageDataObserver observer) {
+        final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_CACHE_FILES, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 /* requireFullPermission= */ true, /* checkShell= */ false,
                 "delete application cache files");
+        final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_INSTANT_APPS);
 
         final PackageParser.Package pkg;
         synchronized (mPackages) {
@@ -19890,15 +19997,25 @@
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
-                synchronized (mInstallLock) {
-                    final int flags = StorageManager.FLAG_STORAGE_DE
-                            | StorageManager.FLAG_STORAGE_CE;
-                    // We're only clearing cache files, so we don't care if the
-                    // app is unfrozen and still able to run
-                    clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
-                    clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                final PackageSetting ps = (PackageSetting) pkg.mExtras;
+                boolean doClearData = true;
+                if (ps != null) {
+                    final boolean targetIsInstantApp =
+                            ps.getInstantApp(UserHandle.getUserId(callingUid));
+                    doClearData = !targetIsInstantApp
+                            || hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
                 }
-                clearExternalStorageDataSync(packageName, userId, false);
+                if (doClearData) {
+                    synchronized (mInstallLock) {
+                        final int flags = StorageManager.FLAG_STORAGE_DE
+                                | StorageManager.FLAG_STORAGE_CE;
+                        // We're only clearing cache files, so we don't care if the
+                        // app is unfrozen and still able to run
+                        clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+                        clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                    }
+                    clearExternalStorageDataSync(packageName, userId, false);
+                }
                 if (observer != null) {
                     try {
                         observer.onRemoveCompleted(packageName, true);
@@ -20148,7 +20265,11 @@
                             android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
                 }
             }
-
+            final PackageSetting ps = mSettings.getPackageLPr(packageName);
+            if (ps != null
+                    && filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return;
+            }
             int user = UserHandle.getCallingUserId();
             if (clearPackagePreferredActivitiesLPw(packageName, user)) {
                 scheduleWritePackageRestrictionsLocked(user);
@@ -20798,7 +20919,7 @@
     public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
         mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         enforceOwnerRights(ownerPackage, callingUid);
         enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
         synchronized (mPackages) {
@@ -20821,7 +20942,7 @@
         if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
             return;
         }
-        int callingUserId = UserHandle.getUserId(callingUid);
+        final int callingUserId = UserHandle.getUserId(callingUid);
         PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
         if (pi == null) {
             throw new IllegalArgumentException("Unknown package " + pkg + " on user "
@@ -23460,13 +23581,14 @@
     public int movePackage(final String packageName, final String volumeUuid) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
 
-        final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+        final int callingUid = Binder.getCallingUid();
+        final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
         final int moveId = mNextMoveId.getAndIncrement();
         mHandler.post(new Runnable() {
             @Override
             public void run() {
                 try {
-                    movePackageInternal(packageName, volumeUuid, moveId, user);
+                    movePackageInternal(packageName, volumeUuid, moveId, callingUid, user);
                 } catch (PackageManagerException e) {
                     Slog.w(TAG, "Failed to move " + packageName, e);
                     mMoveCallbacks.notifyStatusChanged(moveId,
@@ -23478,7 +23600,8 @@
     }
 
     private void movePackageInternal(final String packageName, final String volumeUuid,
-            final int moveId, UserHandle user) throws PackageManagerException {
+            final int moveId, final int callingUid, UserHandle user)
+                    throws PackageManagerException {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
         final PackageManager pm = mContext.getPackageManager();
 
@@ -23498,10 +23621,11 @@
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (pkg == null || ps == null) {
+            if (pkg == null
+                    || ps == null
+                    || filterAppAccessLPr(ps, callingUid, user.getIdentifier())) {
                 throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
             }
-
             if (pkg.applicationInfo.isSystemApp()) {
                 throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
                         "Cannot move system application");
@@ -23971,6 +24095,11 @@
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
             return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
         }
@@ -24687,9 +24816,6 @@
 
     @Override
     public boolean canRequestPackageInstalls(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
-            return false;
-        }
         return canRequestPackageInstallsInternal(packageName, 0, userId,
                 true /* throwIfPermNotDeclared*/);
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 76d5c33..6aba9cb 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1418,7 +1418,7 @@
                     launchHomeFromHotKey();
                     break;
                 case SHORT_PRESS_POWER_GO_HOME:
-                    launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+                    shortPressPowerGoHome();
                     break;
                 case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
                     if (mDismissImeOnBackKeyPressed) {
@@ -1430,8 +1430,7 @@
                             mInputMethodManagerInternal.hideCurrentInputMethod();
                         }
                     } else {
-                        launchHomeFromHotKey(true /* awakenFromDreams */,
-                                false /*respectKeyguard*/);
+                        shortPressPowerGoHome();
                     }
                     break;
                 }
@@ -1439,6 +1438,15 @@
         }
     }
 
+    private void shortPressPowerGoHome() {
+        launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+        if (isKeyguardShowingAndNotOccluded()) {
+            // Notify keyguard so it can do any special handling for the power button since the
+            // device will not power off and only launch home.
+            mKeyguardDelegate.onShortPowerPressedGoHome();
+        }
+    }
+
     private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
         switch (behavior) {
             case MULTI_PRESS_POWER_NOTHING:
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index da90e5a..0121ee1 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -372,6 +372,12 @@
         mKeyguardState.bootCompleted = true;
     }
 
+    public void onShortPowerPressedGoHome() {
+        if (mKeyguardService != null) {
+            mKeyguardService.onShortPowerPressedGoHome();
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + TAG);
         prefix += "  ";
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 0b839b8..425be54 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -218,6 +218,15 @@
         }
     }
 
+    @Override
+    public void onShortPowerPressedGoHome() {
+        try {
+            mService.onShortPowerPressedGoHome();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
     @Override // Binder interface
     public IBinder asBinder() {
         return mService.asBinder();
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index fe90ba9..d4949b6 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -278,6 +278,7 @@
         pw.println("Current WebView Update Service state");
         pw.println(String.format("  Fallback logic enabled: %b",
                 mSystemInterface.isFallbackLogicEnabled()));
+        pw.println(String.format("  Multiprocess enabled: %b", isMultiProcessEnabled()));
         mWebViewUpdater.dumpState(pw);
     }
 }
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 972623c..7eebe39 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -25,6 +25,7 @@
 
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -45,6 +46,7 @@
     private static final int NOTIFICATION_ID = 0;
 
     private static int sNextRequestCode = 0;
+    private static NotificationChannelGroup sChannelGroup;
     private final int mRequestCode;
     private final WindowManagerService mService;
     private String mNotificationTag;
@@ -61,6 +63,12 @@
         mNotificationTag = CHANNEL_PREFIX + mPackageName;
         mRequestCode = sNextRequestCode++;
         mIconUtilities = new IconUtilities(mService.mContext);
+        if (sChannelGroup == null) {
+            sChannelGroup = new NotificationChannelGroup(CHANNEL_PREFIX,
+                    mService.mContext.getString(
+                            R.string.alert_windows_notification_channel_group_name));
+            mNotificationManager.createNotificationChannelGroup(sChannelGroup);
+        }
     }
 
     void post() {
@@ -142,6 +150,7 @@
         channel.enableLights(false);
         channel.enableVibration(false);
         channel.setBlockableSystem(true);
+        channel.setGroup(sChannelGroup.getId());
         mNotificationManager.createNotificationChannel(channel);
     }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 1a685eb..6640184 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -19,7 +19,6 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -381,6 +380,7 @@
                 // if made visible again.
                 wtoken.removeDeadWindows();
                 wtoken.setVisibleBeforeClientHidden();
+                mService.mUnknownAppVisibilityController.appRemovedOrHidden(wtoken);
             } else {
                 if (!mService.mAppTransition.isTransitionSet()
                         && mService.mAppTransition.isReady()) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 37ebfd3..525e0ff 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -52,7 +52,6 @@
 
 import android.annotation.NonNull;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -526,7 +525,7 @@
         boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
 
         mService.mOpeningApps.remove(this);
-        mService.mUnknownAppVisibilityController.appRemoved(this);
+        mService.mUnknownAppVisibilityController.appRemovedOrHidden(this);
         mService.mTaskSnapshotController.onAppRemoved(this);
         waitingToShow = false;
         if (mService.mClosingApps.contains(this)) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 818df01..bfebca8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -163,6 +163,8 @@
 
     @VisibleForTesting
     boolean shouldDeferRemoval() {
+        // TODO: This should probably return false if mChildren.isEmpty() regardless if the stack
+        // is animating...
         return hasWindowsAlive() && mStack.isAnimating();
     }
 
diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
index 8f4f09e..eb751fa 100644
--- a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
+++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
@@ -84,9 +84,9 @@
         return builder.toString();
     }
 
-    void appRemoved(@NonNull AppWindowToken appWindow) {
+    void appRemovedOrHidden(@NonNull AppWindowToken appWindow) {
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App removed appWindow=" + appWindow);
+            Slog.d(TAG, "App removed or hidden appWindow=" + appWindow);
         }
         mUnknownApps.remove(appWindow);
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02fdfee..9d1b3d9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -617,6 +617,11 @@
     WindowState mCurrentFocus = null;
     WindowState mLastFocus = null;
 
+    /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
+    private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
+    /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
+    private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
+
     /** This just indicates the window the input method is on top of, not
      * necessarily the window its input is going to. */
     WindowState mInputMethodTarget = null;
@@ -1381,6 +1386,9 @@
             // From now on, no exceptions or errors allowed!
 
             res = WindowManagerGlobal.ADD_OKAY;
+            if (mCurrentFocus == null) {
+                mWinAddedSinceNullFocus.add(win);
+            }
 
             if (excludeWindowTypeFromTapOutTask(type)) {
                 displayContent.mTapExcludedWindows.add(win);
@@ -1667,6 +1675,9 @@
             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
         }
 
+        if (mCurrentFocus == null) {
+            mWinRemovedSinceNullFocus.add(win);
+        }
         mPendingRemove.remove(win);
         mResizingWindows.remove(win);
         mWindowsChanged = true;
@@ -5804,6 +5815,11 @@
             mCurrentFocus = newFocus;
             mLosingFocus.remove(newFocus);
 
+            if (mCurrentFocus != null) {
+                mWinAddedSinceNullFocus.clear();
+                mWinRemovedSinceNullFocus.clear();
+            }
+
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
             if (imWindowChanged && oldFocus != mInputMethodWindow) {
@@ -6538,6 +6554,12 @@
         if (reason != null) {
             pw.println("  Reason: " + reason);
         }
+        if (!mWinAddedSinceNullFocus.isEmpty()) {
+            pw.println("  Windows added since null focus: " + mWinAddedSinceNullFocus);
+        }
+        if (!mWinRemovedSinceNullFocus.isEmpty()) {
+            pw.println("  Windows removed since null focus: " + mWinRemovedSinceNullFocus);
+        }
         pw.println();
         dumpWindowsNoHeaderLocked(pw, true, null);
         pw.println();
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 39caa3c..ec08874 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -61,6 +61,7 @@
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -102,6 +103,7 @@
     private static final long[] FALLBACK_VIBRATION_PATTERN = new long[] {100, 100, 100};
     private static final VibrationEffect FALLBACK_VIBRATION =
             VibrationEffect.createWaveform(FALLBACK_VIBRATION_PATTERN, -1);
+    private static final int MAX_VIBRATION_DELAY = 1000;
 
     @Before
     public void setUp() {
@@ -309,6 +311,11 @@
                 (AudioAttributes) anyObject());
     }
 
+    private void verifyDelayedVibrateLooped() {
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
+    }
+
     private void verifyStopVibrate() {
         verify(mVibrator, times(1)).cancel();
     }
@@ -506,8 +513,8 @@
 
         VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
 
-        verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), eq(effect),
-                    (AudioAttributes) anyObject());
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                eq(effect), (AudioAttributes) anyObject());
     }
 
     @Test
@@ -521,8 +528,8 @@
 
         mService.buzzBeepBlinkLocked(r);
 
-        verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), eq(FALLBACK_VIBRATION),
-                (AudioAttributes) anyObject());
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
         verify(mRingtonePlayer, never()).playAsync
                 (anyObject(), anyObject(), anyBoolean(), anyObject());
     }
@@ -539,7 +546,7 @@
 
         mService.buzzBeepBlinkLocked(r);
 
-        verifyVibrateLooped();
+        verifyDelayedVibrateLooped();
     }
 
     @Test
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5c40a2c..dfc69ea 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -93,6 +93,8 @@
     private TestableLooper mTestableLooper;
     @Mock
     private RankingHelper mRankingHelper;
+    @Mock
+    private NotificationUsageStats mUsageStats;
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
             TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
     @Mock
@@ -149,7 +151,7 @@
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
         mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
                 mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr,
-                mSnoozeHelper);
+                mSnoozeHelper, mUsageStats);
 
         // Tests call directly into the Binder.
         mBinderService = mNotificationManagerService.getBinderService();
@@ -263,40 +265,37 @@
 
     @Test
     public void testBlockedNotifications_suspended() throws Exception {
-        NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
 
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
         NotificationRecord r = generateNotificationRecord(channel);
-        assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
-        verify(usageStats, times(1)).registerSuspendedByAdmin(eq(r));
+        assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+        verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r));
     }
 
     @Test
     public void testBlockedNotifications_blockedChannel() throws Exception {
-        NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
 
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
         channel.setImportance(NotificationManager.IMPORTANCE_NONE);
         NotificationRecord r = generateNotificationRecord(channel);
-        assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
-        verify(usageStats, times(1)).registerBlocked(eq(r));
+        assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+        verify(mUsageStats, times(1)).registerBlocked(eq(r));
     }
 
     @Test
     public void testBlockedNotifications_blockedApp() throws Exception {
-        NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
 
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
         NotificationRecord r = generateNotificationRecord(channel);
         r.setUserImportance(NotificationManager.IMPORTANCE_NONE);
-        assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
-        verify(usageStats, times(1)).registerBlocked(eq(r));
+        assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+        verify(mUsageStats, times(1)).registerBlocked(eq(r));
     }
 
     @Test
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 0812783..5a6225a 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -35,6 +35,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.media.AudioAttributes;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -44,6 +45,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,6 +74,14 @@
     private final String channelId = "channel";
     NotificationChannel channel =
             new NotificationChannel(channelId, "test", NotificationManager.IMPORTANCE_DEFAULT);
+    private final String channelIdLong =
+            "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there";
+    final String groupId = "group";
+    final String groupIdOverride = "other_group";
+    private final String groupIdLong =
+            "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/";
+    NotificationChannel channelLongId =
+            new NotificationChannel(channelIdLong, "long", NotificationManager.IMPORTANCE_DEFAULT);
     NotificationChannel defaultChannel =
             new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
                     NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -107,7 +118,8 @@
     }
 
     private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
-            boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights) {
+            boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights,
+            String group) {
         when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
         final Builder builder = new Builder(mMockContext)
                 .setContentTitle("foo")
@@ -151,6 +163,9 @@
             builder.setChannelId(channelId);
         }
 
+        if(group != null) {
+            builder.setGroup(group);
+        }
 
         Notification n = builder.build();
         if (preO) {
@@ -172,7 +187,7 @@
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
@@ -185,7 +200,7 @@
         // pre upgrade, custom sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -199,7 +214,7 @@
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -211,7 +226,7 @@
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(null, record.getSound());
@@ -224,7 +239,7 @@
         // post upgrade, default sound.
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -237,7 +252,7 @@
         // pre upgrade, default vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNotNull(record.getVibration());
@@ -249,7 +264,7 @@
         // pre upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_VIBRATION, record.getVibration());
@@ -262,7 +277,7 @@
         // pre upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertTrue(!Objects.equals(CUSTOM_VIBRATION, record.getVibration()));
@@ -274,7 +289,7 @@
         // post upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_CHANNEL_VIBRATION, record.getVibration());
@@ -284,7 +299,7 @@
     public void testImportance_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
     }
@@ -295,7 +310,7 @@
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
@@ -307,7 +322,7 @@
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
@@ -317,7 +332,7 @@
     public void testImportance_upgrade() throws Exception {
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, record.getImportance());
     }
@@ -326,7 +341,7 @@
     public void testLights_preUpgrade_noLight() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNull(record.getLight());
     }
@@ -336,7 +351,7 @@
     public void testLights_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_LIGHT, record.getLight());
     }
@@ -347,7 +362,7 @@
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertFalse(CUSTOM_LIGHT.equals(record.getLight()));
@@ -366,7 +381,7 @@
                 defaultLightColor, defaultLightOn, defaultLightOff);
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, true /*defaultLights */);
+                true /* lights */, true /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(expected, record.getLight());
     }
@@ -382,7 +397,7 @@
                 Color.BLUE, defaultLightOn, defaultLightOff);
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(expected, record.getLight());
     }
@@ -391,8 +406,80 @@
     public void testLights_upgrade_noLight() throws Exception {
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNull(record.getLight());
     }
+
+    @Test
+    public void testLogmakerShortChannel() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        final LogMaker logMaker = record.getLogMaker();
+        assertEquals(channelId,
+                (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID));
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+    }
+
+    @Test
+    public void testLogmakerLongChannel() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+        true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+        false /* lights */, false /*defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channelLongId);
+        final String loggedId = (String)
+            record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID);
+        assertEquals(channelIdLong.substring(0,10), loggedId.substring(0, 10));
+    }
+
+    @Test
+    public void testLogmakerNoGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /*defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertNull(record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+    @Test
+    public void testLogmakerShortGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*reO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+    @Test
+    public void testLogmakerLongGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupIdLong /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        final String loggedId = (String)
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID);
+        assertEquals(groupIdLong.substring(0,10), loggedId.substring(0, 10));
+    }
+
+    @Test
+    public void testLogmakerOverrideGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+        record.setOverrideGroupKey(groupIdOverride);
+        assertEquals(groupIdOverride,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+        record.setOverrideGroupKey(null);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 5a4bb27..4a22a29 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -82,7 +82,7 @@
     public void testAppRemoved() throws Exception {
         final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(mDisplayContent);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token);
-        sWm.mUnknownAppVisibilityController.appRemoved(token);
+        sWm.mUnknownAppVisibilityController.appRemovedOrHidden(token);
         assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
     }
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 0c5e4bd..3788cf33 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.server.voiceinteraction;
 
+import static android.app.ActivityManager.START_ASSISTANT_HIDDEN_SESSION;
+import static android.app.ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION;
 import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
 import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
 
@@ -212,11 +214,11 @@
         try {
             if (mActiveSession == null || token != mActiveSession.mToken) {
                 Slog.w(TAG, "startAssistantActivity does not match active session");
-                return START_VOICE_NOT_ACTIVE_SESSION;
+                return START_ASSISTANT_NOT_ACTIVE_SESSION;
             }
             if (!mActiveSession.mShown) {
                 Slog.w(TAG, "startAssistantActivity not allowed on hidden session");
-                return START_VOICE_HIDDEN_SESSION;
+                return START_ASSISTANT_HIDDEN_SESSION;
             }
             intent = new Intent(intent);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 4267ec4..d394d63 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -453,6 +453,7 @@
                 mShowFlags = 0;
                 mHaveAssistData = false;
                 mAssistData.clear();
+                mPendingShowCallbacks.clear();
                 if (mSession != null) {
                     try {
                         mSession.hide();
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index e53e246..9513517 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -252,6 +252,12 @@
      */
     public static final int WIFI_LOST = 59;
 
+    /**
+     * The call has failed because of access class barring.
+     * {@hide}
+     */
+    public static final int IMS_ACCESS_BLOCKED = 60;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Update toString() with the newly added disconnect type.
@@ -384,6 +390,8 @@
             return "IMEI_NOT_ACCEPTED";
         case WIFI_LOST:
             return "WIFI_LOST";
+        case IMS_ACCESS_BLOCKED:
+            return "IMS_ACCESS_BLOCKED";
         default:
             return "INVALID: " + cause;
         }
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 272653f..4d2f97f 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -664,7 +664,8 @@
                     if (lineCount == 2 && line.contains(SUCCESS_MESSAGE)) {
                         launchSuccess = true;
                     }
-                    if (launchSuccess && lineCount == 4) {
+                    // Parse TotalTime which is the launch time
+                    if (launchSuccess && lineCount == 5) {
                         String launchSplit[] = line.split(":");
                         launchTime = launchSplit[1].trim();
                     }
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 3af0adc..e4bf590 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -42,6 +42,7 @@
     libui \
     libunwind \
     libutils \
+    libvndksupport \
     libcrypto \
     libhidl-gen-utils \
     libhidlbase \
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 241b828..b6922d4 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -16,6 +16,12 @@
 
 package com.android.server.connectivity;
 
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyBoolean;
@@ -222,12 +228,22 @@
 
     private void sendWifiApStateChanged(int state) {
         final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
-        intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, state);
+        intent.putExtra(EXTRA_WIFI_AP_STATE, state);
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    private void verifyInterfaceServingModeStarted() throws Exception {
-        verify(mNMService, times(1)).listInterfaces();
+    private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
+        final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+        intent.putExtra(EXTRA_WIFI_AP_STATE, state);
+        intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
+        intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
+        mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    private void verifyInterfaceServingModeStarted(boolean ifnameKnown) throws Exception {
+        if (!ifnameKnown) {
+            verify(mNMService, times(1)).listInterfaces();
+        }
         verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
         verify(mNMService, times(1))
                 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
@@ -243,18 +259,21 @@
         mIntents.remove(bcast);
     }
 
-    @Test
-    public void workingLocalOnlyHotspot() throws Exception {
+    public void workingLocalOnlyHotspot(boolean enrichedApBroadcast) throws Exception {
         when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
 
         // Emulate externally-visible WifiManager effects, causing the
         // per-interface state machine to start up, and telling us that
         // hotspot mode is to be started.
         mTethering.interfaceStatusChanged(mTestIfname, true);
-        sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+        if (enrichedApBroadcast) {
+            sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_LOCAL_ONLY);
+        } else {
+            sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
+        }
         mLooper.dispatchAll();
 
-        verifyInterfaceServingModeStarted();
+        verifyInterfaceServingModeStarted(enrichedApBroadcast);
         verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
@@ -295,7 +314,16 @@
     }
 
     @Test
-    public void workingWifiTethering() throws Exception {
+    public void workingLocalOnlyHotspotLegacyApBroadcast() throws Exception {
+        workingLocalOnlyHotspot(false);
+    }
+
+    @Test
+    public void workingLocalOnlyHotspotEnrichedApBroadcast() throws Exception {
+        workingLocalOnlyHotspot(true);
+    }
+
+    public void workingWifiTethering(boolean enrichedApBroadcast) throws Exception {
         when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
 
@@ -311,10 +339,14 @@
         // per-interface state machine to start up, and telling us that
         // tethering mode is to be started.
         mTethering.interfaceStatusChanged(mTestIfname, true);
-        sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+        if (enrichedApBroadcast) {
+            sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
+        } else {
+            sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
+        }
         mLooper.dispatchAll();
 
-        verifyInterfaceServingModeStarted();
+        verifyInterfaceServingModeStarted(enrichedApBroadcast);
         verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
@@ -376,6 +408,16 @@
     }
 
     @Test
+    public void workingWifiTetheringLegacyApBroadcast() throws Exception {
+        workingWifiTethering(false);
+    }
+
+    @Test
+    public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
+        workingWifiTethering(true);
+    }
+
+    @Test
     public void failureEnablingIpForwarding() throws Exception {
         when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
diff --git a/tests/testables/src/android/testing/ViewUtils.java b/tests/testables/src/android/testing/ViewUtils.java
index 7478998..1c6016e 100644
--- a/tests/testables/src/android/testing/ViewUtils.java
+++ b/tests/testables/src/android/testing/ViewUtils.java
@@ -39,8 +39,7 @@
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 LayoutParams.TYPE_APPLICATION_OVERLAY,
                 0, PixelFormat.TRANSLUCENT);
-        InstrumentationRegistry.getContext()
-                .getSystemService(WindowManager.class).addView(view, lp);
+        view.getContext().getSystemService(WindowManager.class).addView(view, lp);
     }
 
     /**
@@ -49,7 +48,6 @@
      * This is currently done by removing the view from a window.
      */
     public static void detachView(View view) {
-        InstrumentationRegistry.getContext()
-                .getSystemService(WindowManager.class).removeViewImmediate(view);
+        view.getContext().getSystemService(WindowManager.class).removeViewImmediate(view);
     }
 }
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index bc13378..084325a 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -415,6 +415,10 @@
   if (resource_type == "item") {
     can_be_bag = false;
 
+    // The default format for <item> is any. If a format attribute is present, that one will
+    // override the default.
+    resource_format = android::ResTable_map::TYPE_ANY;
+
     // Items have their type encoded in the type attribute.
     if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
       resource_type = maybe_type.value().to_string();
@@ -481,8 +485,8 @@
       out_resource->name.type = item_iter->second.type;
       out_resource->name.entry = maybe_name.value().to_string();
 
-      // Only use the implicit format for this type if it wasn't overridden.
-      if (!resource_format) {
+      // Only use the implied format of the type when there is no explicit format.
+      if (resource_format == 0u) {
         resource_format = item_iter->second.format;
       }
 
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index e3abde6..e60ef66 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -25,7 +25,9 @@
 #include "test/Test.h"
 #include "xml/XmlPullParser.h"
 
-using android::StringPiece;
+using ::android::StringPiece;
+using ::testing::Eq;
+using ::testing::NotNull;
 
 namespace aapt {
 
@@ -791,15 +793,25 @@
 }
 
 TEST_F(ResourceParserTest, ParseItemElementWithFormat) {
-  std::string input =
-      R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF";
+  std::string input = R"(<item name="foo" type="integer" format="float">0.3</item>)";
   ASSERT_TRUE(TestParse(input));
 
-  BinaryPrimitive* val =
-      test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
-  ASSERT_NE(nullptr, val);
+  BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+  ASSERT_THAT(val, NotNull());
+  EXPECT_THAT(val->value.dataType, Eq(android::Res_value::TYPE_FLOAT));
 
-  EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType);
+  input = R"(<item name="bar" type="integer" format="fraction">100</item>)";
+  ASSERT_FALSE(TestParse(input));
+}
+
+// An <item> without a format specifier accepts all types of values.
+TEST_F(ResourceParserTest, ParseItemElementWithoutFormat) {
+  std::string input = R"(<item name="foo" type="integer">100%p</item>)";
+  ASSERT_TRUE(TestParse(input));
+
+  BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+  ASSERT_THAT(val, NotNull());
+  EXPECT_THAT(val->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
 }
 
 TEST_F(ResourceParserTest, ParseConfigVaryingItem) {
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
index 91f8bfd..5104f82 100644
--- a/tools/aapt2/integration-tests/AppOne/res/values/test.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
@@ -30,6 +30,8 @@
         <flag name="weak" value="4" />
     </attr>
 
+    <item name="value_that_allows_any_format" type="integer">-100%p</item>
+
     <!-- Override the Widget styleable declared in StaticLibOne.
          This should merge the two when built in overlay mode. -->
     <declare-styleable name="Widget">
diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.aidl b/wifi/java/android/net/wifi/hotspot2/OsuProvider.aidl
new file mode 100644
index 0000000..23d0f22
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.net.wifi.hotspot2;
+
+parcelable OsuProvider;
diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
new file mode 100644
index 0000000..25dcdd8
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
@@ -0,0 +1,231 @@
+/*
+ * 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 android.net.wifi.hotspot2;
+
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.net.wifi.WifiSsid;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Contained information for a Hotspot 2.0 OSU (Online Sign-Up provider).
+ *
+ * @hide
+ */
+public final class OsuProvider implements Parcelable {
+    /**
+     * OSU (Online Sign-Up) method: OMA DM (Open Mobile Alliance Device Management).
+     * For more info, refer to Section 8.3 of the Hotspot 2.0 Release 2 Technical Specification.
+     */
+    public static final int METHOD_OMA_DM = 0;
+
+    /**
+     * OSU (Online Sign-Up) method: SOAP XML SPP (Subscription Provisioning Protocol).
+     * For more info, refer to Section 8.4 of the Hotspot 2.0 Release 2 Technical Specification.
+     */
+    public static final int METHOD_SOAP_XML_SPP = 1;
+
+    /**
+     * SSID of the network to connect for service sign-up.
+     */
+    private final WifiSsid mOsuSsid;
+
+    /**
+     * Friendly name of the OSU provider.
+     */
+    private final String mFriendlyName;
+
+    /**
+     * Description of the OSU provider.
+     */
+    private final String mServiceDescription;
+
+    /**
+     * URI to browse to for service sign-up.
+     */
+    private final Uri mServerUri;
+
+    /**
+     * Network Access Identifier used for authenticating with the OSU network when OSEN is used.
+     */
+    private final String mNetworkAccessIdentifier;
+
+    /**
+     * List of OSU (Online Sign-Up) method supported.
+     */
+    private final List<Integer> mMethodList;
+
+    /**
+     * Icon data for the OSU (Online Sign-Up) provider.
+     */
+    private final Icon mIcon;
+
+    public OsuProvider(WifiSsid osuSsid, String friendlyName, String serviceDescription,
+            Uri serverUri, String nai, List<Integer> methodList, Icon icon) {
+        mOsuSsid = osuSsid;
+        mFriendlyName = friendlyName;
+        mServiceDescription = serviceDescription;
+        mServerUri = serverUri;
+        mNetworkAccessIdentifier = nai;
+        if (methodList == null) {
+            mMethodList = new ArrayList<>();
+        } else {
+            mMethodList = new ArrayList<>(methodList);
+        }
+        mIcon = icon;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param source The source to copy from
+     */
+    public OsuProvider(OsuProvider source) {
+        if (source == null) {
+            mOsuSsid = null;
+            mFriendlyName = null;
+            mServiceDescription = null;
+            mServerUri = null;
+            mNetworkAccessIdentifier = null;
+            mMethodList = new ArrayList<>();
+            mIcon = null;
+            return;
+        }
+
+        mOsuSsid = source.mOsuSsid;
+        mFriendlyName = source.mFriendlyName;
+        mServiceDescription = source.mServiceDescription;
+        mServerUri = source.mServerUri;
+        mNetworkAccessIdentifier = source.mNetworkAccessIdentifier;
+        if (source.mMethodList == null) {
+            mMethodList = new ArrayList<>();
+        } else {
+            mMethodList = new ArrayList<>(source.mMethodList);
+        }
+        mIcon = source.mIcon;
+    }
+
+    public WifiSsid getOsuSsid() {
+        return mOsuSsid;
+    }
+
+    public String getFriendlyName() {
+        return mFriendlyName;
+    }
+
+    public String getServiceDescription() {
+        return mServiceDescription;
+    }
+
+    public Uri getServerUri() {
+        return mServerUri;
+    }
+
+    public String getNetworkAccessIdentifier() {
+        return mNetworkAccessIdentifier;
+    }
+
+    public List<Integer> getMethodList() {
+        return Collections.unmodifiableList(mMethodList);
+    }
+
+    public Icon getIcon() {
+        return mIcon;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mOsuSsid, flags);
+        dest.writeString(mFriendlyName);
+        dest.writeString(mServiceDescription);
+        dest.writeParcelable(mServerUri, flags);
+        dest.writeString(mNetworkAccessIdentifier);
+        dest.writeList(mMethodList);
+        dest.writeParcelable(mIcon, flags);
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        if (!(thatObject instanceof OsuProvider)) {
+            return false;
+        }
+        OsuProvider that = (OsuProvider) thatObject;
+        return (mOsuSsid == null ? that.mOsuSsid == null : mOsuSsid.equals(that.mOsuSsid))
+                && TextUtils.equals(mFriendlyName, that.mFriendlyName)
+                && TextUtils.equals(mServiceDescription, that.mServiceDescription)
+                && (mServerUri == null ? that.mServerUri == null
+                            : mServerUri.equals(that.mServerUri))
+                && TextUtils.equals(mNetworkAccessIdentifier, that.mNetworkAccessIdentifier)
+                && (mMethodList == null ? that.mMethodList == null
+                            : mMethodList.equals(that.mMethodList))
+                && (mIcon == null ? that.mIcon == null : mIcon.sameAs(that.mIcon));
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mOsuSsid, mFriendlyName, mServiceDescription, mServerUri,
+                mNetworkAccessIdentifier, mMethodList, mIcon);
+    }
+
+    @Override
+    public String toString() {
+        return "OsuProvider{mOsuSsid=" + mOsuSsid
+                + " mFriendlyName=" + mFriendlyName
+                + " mServiceDescription=" + mServiceDescription
+                + " mServerUri=" + mServerUri
+                + " mNetworkAccessIdentifier=" + mNetworkAccessIdentifier
+                + " mMethodList=" + mMethodList
+                + " mIcon=" + mIcon;
+    }
+
+    public static final Creator<OsuProvider> CREATOR =
+        new Creator<OsuProvider>() {
+            @Override
+            public OsuProvider createFromParcel(Parcel in) {
+                WifiSsid osuSsid = (WifiSsid) in.readParcelable(null);
+                String friendlyName = in.readString();
+                String serviceDescription = in.readString();
+                Uri serverUri = (Uri) in.readParcelable(null);
+                String nai = in.readString();
+                List<Integer> methodList = new ArrayList<>();
+                in.readList(methodList, null);
+                Icon icon = (Icon) in.readParcelable(null);
+                return new OsuProvider(osuSsid, friendlyName, serviceDescription, serverUri,
+                        nai, methodList, icon);
+            }
+
+            @Override
+            public OsuProvider[] newArray(int size) {
+                return new OsuProvider[size];
+            }
+        };
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
new file mode 100644
index 0000000..9670bfa
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 android.net.wifi.hotspot2;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.net.wifi.WifiSsid;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.OsuProvider}.
+ */
+@SmallTest
+public class OsuProviderTest {
+    private static final WifiSsid TEST_SSID =
+            WifiSsid.createFromByteArray("TEST SSID".getBytes(StandardCharsets.UTF_8));
+    private static final String TEST_FRIENDLY_NAME = "Friendly Name";
+    private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
+    private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
+    private static final String TEST_NAI = "test.access.com";
+    private static final List<Integer> TEST_METHOD_LIST =
+            Arrays.asList(OsuProvider.METHOD_SOAP_XML_SPP);
+    private static final Icon TEST_ICON = Icon.createWithData(new byte[10], 0, 10);
+
+    /**
+     * Verify parcel write and read consistency for the given {@link OsuProvider}.
+     *
+     * @param writeInfo The {@link OsuProvider} to verify
+     * @throws Exception
+     */
+    private static void verifyParcel(OsuProvider writeInfo) throws Exception {
+        Parcel parcel = Parcel.obtain();
+        writeInfo.writeToParcel(parcel, 0);
+
+        parcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        OsuProvider readInfo = OsuProvider.CREATOR.createFromParcel(parcel);
+        assertEquals(writeInfo, readInfo);
+    }
+
+    /**
+     * Verify parcel read/write for an OSU provider containing no information.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithEmptyProviderInfo() throws Exception {
+        verifyParcel(new OsuProvider(null, null, null, null, null, null, null));
+    }
+
+    /**
+     * Verify parcel read/write for an OSU provider containing full information.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithFullProviderInfo() throws Exception {
+        verifyParcel(new OsuProvider(TEST_SSID, TEST_FRIENDLY_NAME, TEST_SERVICE_DESCRIPTION,
+                TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON));
+    }
+
+    /**
+     * Verify copy constructor with a null source.
+     * @throws Exception
+     */
+    @Test
+    public void verifyCopyConstructorWithNullSource() throws Exception {
+        OsuProvider expected = new OsuProvider(null, null, null, null, null, null, null);
+        assertEquals(expected, new OsuProvider(null));
+    }
+
+    /**
+     * Verify copy constructor with a valid source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyCopyConstructorWithValidSource() throws Exception {
+        OsuProvider source = new OsuProvider(TEST_SSID, TEST_FRIENDLY_NAME, TEST_SERVICE_DESCRIPTION,
+                TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON);
+        assertEquals(source, new OsuProvider(source));
+    }
+
+    /**
+     * Verify getter methods.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyGetters() throws Exception {
+        OsuProvider provider = new OsuProvider(TEST_SSID, TEST_FRIENDLY_NAME,
+                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON);
+        assertTrue(TEST_SSID.equals(provider.getOsuSsid()));
+        assertTrue(TEST_FRIENDLY_NAME.equals(provider.getFriendlyName()));
+        assertTrue(TEST_SERVICE_DESCRIPTION.equals(provider.getServiceDescription()));
+        assertTrue(TEST_SERVER_URI.equals(provider.getServerUri()));
+        assertTrue(TEST_NAI.equals(provider.getNetworkAccessIdentifier()));
+        assertTrue(TEST_METHOD_LIST.equals(provider.getMethodList()));
+        assertTrue(TEST_ICON.sameAs(provider.getIcon()));
+    }
+}